[MIG] hr_effective_attendance_period: migrate to 18.0
This commit is contained in:
67
hr_effective_attendance_period/README.rst
Normal file
67
hr_effective_attendance_period/README.rst
Normal file
@@ -0,0 +1,67 @@
|
||||
==============================
|
||||
hr_effective_attendance_period
|
||||
==============================
|
||||
|
||||
Provide indication that attendance periods are effectively worked or not.
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
This module adds a boolean field on working time attendance lines to mark
|
||||
which periods are effectively worked by employees. It provides utility methods
|
||||
on the resource calendar to determine:
|
||||
|
||||
- Whether a day is a working day
|
||||
- Whether a day is a full working day (both morning and afternoon)
|
||||
- Whether all attendances of a day are effectively worked (no leaves)
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Use Odoo normal module installation procedure to install
|
||||
``hr_effective_attendance_period``.
|
||||
|
||||
This module depends on:
|
||||
|
||||
* ``base`` (Odoo core)
|
||||
* ``resource`` (Odoo core)
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Go to ``Configuration > Technical > Resource > Working Times`` and create
|
||||
Working Times for your company. For each attendance line, check
|
||||
``Effective Attendance Period`` to indicate which periods are effectively
|
||||
attended by employees.
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
None yet.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `our issues website <https://github.com/elabore-coop/hr-tools/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smash it by providing detailed and welcomed feedback.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Stéphan Sainléger
|
||||
|
||||
Funders
|
||||
-------
|
||||
|
||||
The development of this module has been financially supported by:
|
||||
|
||||
* Elabore (https://elabore.coop)
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
This module is maintained by Elabore.
|
||||
1
hr_effective_attendance_period/__init__.py
Normal file
1
hr_effective_attendance_period/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
24
hr_effective_attendance_period/__manifest__.py
Normal file
24
hr_effective_attendance_period/__manifest__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright 2023 Stéphan Sainléger (Elabore)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "hr_effective_attendance_period",
|
||||
"version": "18.0.1.0.0",
|
||||
"author": "Elabore",
|
||||
"website": "https://git.elabore.coop/elabore/hr-tools",
|
||||
"maintainer": "Stéphan Sainléger",
|
||||
"license": "AGPL-3",
|
||||
"category": "Tools",
|
||||
"summary": "Indicate whether attendance periods are effectively worked",
|
||||
# any module necessary for this one to work correctly
|
||||
"depends": [
|
||||
"base",
|
||||
"resource",
|
||||
],
|
||||
"data": [
|
||||
"views/resource_views.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"auto_install": False,
|
||||
"application": False,
|
||||
}
|
||||
1
hr_effective_attendance_period/i18n/README
Normal file
1
hr_effective_attendance_period/i18n/README
Normal file
@@ -0,0 +1 @@
|
||||
This directory should contain the *.po for Odoo translation.
|
||||
49
hr_effective_attendance_period/i18n/fr.po
Normal file
49
hr_effective_attendance_period/i18n/fr.po
Normal file
@@ -0,0 +1,49 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * hr_effective_attendance_period
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-01-24 21:50+0000\n"
|
||||
"PO-Revision-Date: 2023-01-24 21:50+0000\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_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar__display_name
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nom affiché"
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance__effective_attendance_period
|
||||
msgid "Effective Attendance Period"
|
||||
msgstr "Présence effective"
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar__id
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar____last_update
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Dernière modification le"
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model,name:hr_effective_attendance_period.model_resource_calendar
|
||||
msgid "Resource Working Time"
|
||||
msgstr "Temps de travail de la ressource"
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model,name:hr_effective_attendance_period.model_resource_calendar_attendance
|
||||
msgid "Work Detail"
|
||||
msgstr "Détail du travail"
|
||||
@@ -0,0 +1,49 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * hr_effective_attendance_period
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-01-24 21:49+0000\n"
|
||||
"PO-Revision-Date: 2023-01-24 21:49+0000\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_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar__display_name
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance__effective_attendance_period
|
||||
msgid "Effective Attendance Period"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar__id
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar____last_update
|
||||
#: model:ir.model.fields,field_description:hr_effective_attendance_period.field_resource_calendar_attendance____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model,name:hr_effective_attendance_period.model_resource_calendar
|
||||
msgid "Resource Working Time"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_effective_attendance_period
|
||||
#: model:ir.model,name:hr_effective_attendance_period.model_resource_calendar_attendance
|
||||
msgid "Work Detail"
|
||||
msgstr ""
|
||||
1
hr_effective_attendance_period/models/__init__.py
Normal file
1
hr_effective_attendance_period/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import resource
|
||||
97
hr_effective_attendance_period/models/resource.py
Normal file
97
hr_effective_attendance_period/models/resource.py
Normal file
@@ -0,0 +1,97 @@
|
||||
import math
|
||||
from datetime import timedelta
|
||||
|
||||
import pytz
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResourceCalendarAttendance(models.Model):
|
||||
_inherit = "resource.calendar.attendance"
|
||||
|
||||
effective_attendance_period = fields.Boolean(store=True)
|
||||
|
||||
|
||||
class ResourceCalendar(models.Model):
|
||||
_inherit = "resource.calendar"
|
||||
|
||||
def _retrieve_day_matching_attendances(self, day):
|
||||
domain = [
|
||||
("calendar_id", "=", self.id),
|
||||
("dayofweek", "=", day.weekday()),
|
||||
("effective_attendance_period", "=", True),
|
||||
]
|
||||
if self.two_weeks_calendar:
|
||||
# Employee has Even/Odd weekly calendar
|
||||
week_type = 1 if int(math.floor((day.toordinal() - 1) / 7) % 2) else 0
|
||||
domain.append(("week_type", "=", week_type))
|
||||
result = self.env["resource.calendar.attendance"].search(domain)
|
||||
return result
|
||||
|
||||
def is_working_day(self, day):
|
||||
day_attendances = self._retrieve_day_matching_attendances(day)
|
||||
if len(day_attendances) == 0:
|
||||
# This day of the week is not supposed to be a working day
|
||||
return False
|
||||
else:
|
||||
# This day of the week is supposed to be a working day
|
||||
return True
|
||||
|
||||
def is_full_working_day(self, day):
|
||||
day_attendances = self._retrieve_day_matching_attendances(day)
|
||||
morning_worked = (
|
||||
len(day_attendances.filtered(lambda x: x.day_period == "morning")) > 0
|
||||
)
|
||||
afternoon_worked = (
|
||||
len(day_attendances.filtered(lambda x: x.day_period == "afternoon")) > 0
|
||||
)
|
||||
return morning_worked and afternoon_worked
|
||||
|
||||
def _compute_datetime_in_utc_tz(self, date):
|
||||
user_tz = pytz.timezone(self.env.context.get("tz", "utc") or "utc")
|
||||
return user_tz.localize(date).astimezone(pytz.utc)
|
||||
|
||||
def _is_worked_attendance(self, resource, day, attendance):
|
||||
attendance_start = fields.Datetime.to_datetime(day.date()) + timedelta(
|
||||
hours=attendance.hour_from
|
||||
)
|
||||
attendance_end = fields.Datetime.to_datetime(day.date()) + timedelta(
|
||||
hours=attendance.hour_to
|
||||
)
|
||||
utc_start = self._compute_datetime_in_utc_tz(attendance_start)
|
||||
utc_end = self._compute_datetime_in_utc_tz(attendance_end)
|
||||
resource_leaves = (
|
||||
self.env["resource.calendar.leaves"]
|
||||
.sudo()
|
||||
.search(
|
||||
[
|
||||
("company_id", "=", resource.company_id.id),
|
||||
("date_from", "<=", utc_start),
|
||||
("date_to", ">=", utc_end),
|
||||
"|",
|
||||
("resource_id", "=", resource.id),
|
||||
("resource_id", "=", None),
|
||||
]
|
||||
)
|
||||
)
|
||||
if resource_leaves:
|
||||
return False
|
||||
else:
|
||||
# a part or the whole attendance is worked
|
||||
return True
|
||||
|
||||
def is_worked_day(self, resource, day):
|
||||
day_attendances = self._retrieve_day_matching_attendances(day)
|
||||
# If at least one attendance is worked, return True
|
||||
for attendance in day_attendances:
|
||||
if self._is_worked_attendance(resource, day, attendance):
|
||||
return True
|
||||
return False
|
||||
|
||||
def all_attendances_worked(self, resource, day):
|
||||
day_attendances = self._retrieve_day_matching_attendances(day)
|
||||
# If at least one attendance is not worked, return False
|
||||
for attendance in day_attendances:
|
||||
if not self._is_worked_attendance(resource, day, attendance):
|
||||
return False
|
||||
return True
|
||||
36
hr_effective_attendance_period/views/resource_views.xml
Normal file
36
hr_effective_attendance_period/views/resource_views.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record
|
||||
id="view_resource_calendar_attendance_tree_inherit_effective_attendance"
|
||||
model="ir.ui.view"
|
||||
>
|
||||
<field name="name">resource.calendar.attendance.view.list.inherit</field>
|
||||
<field name="model">resource.calendar.attendance</field>
|
||||
<field
|
||||
name="inherit_id"
|
||||
ref="resource.view_resource_calendar_attendance_tree"
|
||||
/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='week_type']" position="after">
|
||||
<field name="effective_attendance_period" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record
|
||||
id="view_resource_calendar_attendance_form_inherit_effective_attendance"
|
||||
model="ir.ui.view"
|
||||
>
|
||||
<field name="name">resource.calendar.attendance.view.list.inherit</field>
|
||||
<field name="model">resource.calendar.attendance</field>
|
||||
<field
|
||||
name="inherit_id"
|
||||
ref="resource.view_resource_calendar_attendance_form"
|
||||
/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='day_period']" position="after">
|
||||
<field name="effective_attendance_period" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user