Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions hr_work_entry_contract_constrained_attendance/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
=============================================
Constrain Attendance Work Entries to Contract
=============================================

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

.. |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-coopiteasy%2Fcie--hr-lightgray.png?logo=github
:target: https://github.com/coopiteasy/cie-hr/tree/18.0/hr_work_entry_contract_constrained_attendance
:alt: coopiteasy/cie-hr

|badge1| |badge2| |badge3|

Constrain work entries generated from attendances to the contract's
working schedule.

**Table of contents**

.. contents::
:local:

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

Bugs are tracked on `GitHub Issues <https://github.com/coopiteasy/cie-hr/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/coopiteasy/cie-hr/issues/new?body=module:%20hr_work_entry_contract_constrained_attendance%0Aversion:%2018.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
-------

* Coop IT Easy SC

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

- `Coop IT Easy SC <https://coopiteasy.be>`__:

- hugues de keyzer

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

This module is part of the `coopiteasy/cie-hr <https://github.com/coopiteasy/cie-hr/tree/18.0/hr_work_entry_contract_constrained_attendance>`_ project on GitHub.

You are welcome to contribute.
5 changes: 5 additions & 0 deletions hr_work_entry_contract_constrained_attendance/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from . import models
22 changes: 22 additions & 0 deletions hr_work_entry_contract_constrained_attendance/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

{
"name": "Constrain Attendance Work Entries to Contract",
"summary": (
"Constrain work entries generated from attendances to the contract's "
"working schedule"
),
"version": "18.0.1.0.0",
"category": "Human Resources/Employees",
"website": "https://github.com/coopiteasy/cie-hr",
"author": "Coop IT Easy SC",
"license": "AGPL-3",
"depends": [
"hr_work_entry_contract_attendance_oca",
],
"data": [
"views/res_config_settings_views.xml",
],
}
45 changes: 45 additions & 0 deletions hr_work_entry_contract_constrained_attendance/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_work_entry_contract_constrained_attendance
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model.fields,field_description:hr_work_entry_contract_constrained_attendance.field_res_company__absence_hr_work_entry_type_id
#: model:ir.model.fields,field_description:hr_work_entry_contract_constrained_attendance.field_res_config_settings__absence_hr_work_entry_type_id
#: model_terms:ir.ui.view,arch_db:hr_work_entry_contract_constrained_attendance.res_config_settings_view_form
msgid "Absence Work Entry Type"
msgstr "Type de prestation pour les absences"

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model,name:hr_work_entry_contract_constrained_attendance.model_res_company
msgid "Companies"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model,name:hr_work_entry_contract_constrained_attendance.model_res_config_settings
msgid "Config Settings"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model,name:hr_work_entry_contract_constrained_attendance.model_hr_contract
msgid "Employee Contract"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model_terms:ir.ui.view,arch_db:hr_work_entry_contract_constrained_attendance.res_config_settings_view_form
msgid "Work entry type to use for work entries corresponding to an absence."
msgstr ""
"Type de prestation à utiliser pour les prestations correspondant à une "
"absence."
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_work_entry_contract_constrained_attendance
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model.fields,field_description:hr_work_entry_contract_constrained_attendance.field_res_company__absence_hr_work_entry_type_id
#: model:ir.model.fields,field_description:hr_work_entry_contract_constrained_attendance.field_res_config_settings__absence_hr_work_entry_type_id
#: model_terms:ir.ui.view,arch_db:hr_work_entry_contract_constrained_attendance.res_config_settings_view_form
msgid "Absence Work Entry Type"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model,name:hr_work_entry_contract_constrained_attendance.model_res_company
msgid "Companies"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model,name:hr_work_entry_contract_constrained_attendance.model_res_config_settings
msgid "Config Settings"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model:ir.model,name:hr_work_entry_contract_constrained_attendance.model_hr_contract
msgid "Employee Contract"
msgstr ""

#. module: hr_work_entry_contract_constrained_attendance
#: model_terms:ir.ui.view,arch_db:hr_work_entry_contract_constrained_attendance.res_config_settings_view_form
msgid "Work entry type to use for work entries corresponding to an absence."
msgstr ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from . import hr_contract
from . import res_company
from . import res_config_settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from datetime import timedelta

import pytz

from odoo import api, fields, models

from odoo.addons.hr_work_entry_contract.models.hr_work_intervals import WorkIntervals


class HrContract(models.Model):
_inherit = "hr.contract"

def _get_open_hr_attendances(self, start_dt, end_dt):
# return attendances that are still open and that started in the
# interval
return self.env["hr.attendance"].search(
[
("employee_id", "=", self.employee_id.id),
("check_out", "=", False),
("check_in", ">=", start_dt),
("check_in", "<=", end_dt),
]
)

@api.model
def _constrain_hr_attendance_intervals_to_contract(
self, hr_attendance_intervals, contract_intervals, limit_dt
):
"""
Constrain hr.attendance work intervals to the contract attendance
intervals, and drop all intervals that end after limit_dt.
"""
# intersection with the attendances first return the attendance
# intervals constrained to the contract intervals, but still linked to
# the hr.attendance record.
presence_intervals = hr_attendance_intervals & contract_intervals
absence_intervals = contract_intervals - hr_attendance_intervals
all_intervals = presence_intervals | absence_intervals
return WorkIntervals(filter(lambda x: x[1] < limit_dt, all_intervals))

def _get_attendance_intervals(self, start_dt, end_dt):
result = super()._get_attendance_intervals(start_dt, end_dt)
contracts = self.filtered(lambda c: c.work_entry_source == "attendance_oca")
contract_intervals = contracts._get_hr_attendance_contract_intervals(
start_dt, end_dt
)
now = fields.Datetime.now()
# limit datetime for attendances that don't have a check_out date.
default_check_out_dt = now + timedelta(minutes=1)
now_with_tz = pytz.utc.localize(now)
for contract in contracts:
open_hr_attendances = contract._get_open_hr_attendances(start_dt, end_dt)
open_hr_attendance_intervals = self._hr_attendances_to_work_intervals(
open_hr_attendances, default_check_out_dt=default_check_out_dt
)
resource_id = contract.employee_id.resource_id.id
intervals = contract._constrain_hr_attendance_intervals_to_contract(
result[resource_id] | open_hr_attendance_intervals,
contract_intervals[resource_id],
now_with_tz,
)
result[resource_id] = intervals
return result

def _get_interval_work_entry_type(self, interval):
if (
self.work_entry_source == "attendance_oca"
and interval[2]._name != "hr.attendance"
):
return self.env.company.absence_hr_work_entry_type_id
return super()._get_interval_work_entry_type(interval)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from odoo import fields, models


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

def _get_default_absence_hr_work_entry_type(self):
return self.env.ref("hr_work_entry_contract.work_entry_type_unpaid_leave")

absence_hr_work_entry_type_id = fields.Many2one(
"hr.work.entry.type",
"Absence Work Entry Type",
default=_get_default_absence_hr_work_entry_type,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from odoo import fields, models


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

absence_hr_work_entry_type_id = fields.Many2one(
related="company_id.absence_hr_work_entry_type_id", readonly=False
)
3 changes: 3 additions & 0 deletions hr_work_entry_contract_constrained_attendance/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* [Coop IT Easy SC](https://coopiteasy.be):
* hugues de keyzer
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Constrain work entries generated from attendances to the contract's working schedule.
Loading
Loading