Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,45 @@
# Resource Leaves Geographic
Odoo addon: resource_leaves_geographic
## Installation
```bash
pip install odoo-bringout-oca-hr-holidays-resource_leaves_geographic
```
## Dependencies
This addon depends on:
- resource
- hr_holidays
## Manifest Information
- **Name**: Resource Leaves Geographic
- **Version**: 16.0.1.0.1
- **Category**: Human Resources/Time Off
- **License**: LGPL-3
- **Installable**: True
## Source
Based on [OCA/hr-holidays](https://github.com/OCA/hr-holidays) branch 16.0, addon `resource_leaves_geographic`.
## License
This package maintains the original LGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Resource_leaves_geographic Module - resource_leaves_geographic
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for resource_leaves_geographic. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,3 @@
# Controllers
This module does not define custom HTTP controllers.

View file

@ -0,0 +1,6 @@
# Dependencies
This addon depends on:
- [resource](../../odoo-bringout-oca-ocb-resource)
- [hr_holidays](../../odoo-bringout-oca-ocb-hr_holidays)

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon resource_leaves_geographic or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-hr-holidays-resource_leaves_geographic"
# or
uv pip install odoo-bringout-oca-hr-holidays-resource_leaves_geographic"
```

View file

@ -0,0 +1,14 @@
# Models
Detected core models and extensions in resource_leaves_geographic.
```mermaid
classDiagram
class hr_employee
class resource_calendar
class resource_calendar_leaves
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: resource_leaves_geographic. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon resource_leaves_geographic
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,8 @@
# Security
This module does not define custom security rules or access controls beyond Odoo defaults.
Default Odoo security applies:
- Base user access through standard groups
- Model access inherited from dependencies
- No custom row-level security rules

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon resource_leaves_geographic
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-hr-holidays-resource_leaves_geographic"
version = "16.0.0"
description = "Resource Leaves Geographic - Add geographic State to Resource Calendar Leaves"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-resource>=16.0.0",
"odoo-bringout-oca-hr-holidays-hr_holidays>=16.0.0",
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["resource_leaves_geographic"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]

View file

@ -0,0 +1,139 @@
==========================
Resource Leaves Geographic
==========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:19175838a39febb826f0243ad4ae704b07ae0ef0ec132b3c57fae3cb8b1693b2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--holidays-lightgray.png?logo=github
:target: https://github.com/OCA/hr-holidays/tree/16.0/resource_leaves_geographic
:alt: OCA/hr-holidays
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/hr-holidays-16-0/hr-holidays-16-0-resource_leaves_geographic
: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-holidays&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module extends the functionality of Public Holidays to support
States and allow you to define Local Holidays more easily in the Company
Calendar.
Shows on Time Off all the holidays (with/without State) in the Public
Holidays section. Public Holidays (without State) always will have grey
background. Local holidays displayed with a grey background in the
calendar view belong to the Employee currently viewing the calendar or
to the single Employee selected from the Employee Form view.
This module is compatible with Attendances and Contracts (but those
modules are not required).
.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
`More details on development status <https://odoo-community.org/page/development-status>`_
**Table of contents**
.. contents::
:local:
Use Cases / Context
===================
This module was developed because in order to differentiate local
Employee holidays, they must be added to their calendars instead of
being able to mark them on the general company calendar.
This will be useful for you if you want to be able to create holidays by
State in the company calendar and have them automatically applied to all
employees based on their workplace.
Usage
=====
To use this module, you need to:
1. Go to Time Off app > Configuration > Public Holidays
2. Create a Public Holiday without State with name *Local Holiday*
3. Create an *Employee 1* and set his Work Address in the same State
than your *Local Holiday*
4. Create an *Employee 2* and set his Work Address in other State than
your *Local Holiday*
5. Go to Time Off > Overview and check the grey background is only on
*Employee 1* on the days used in *Local Holiday*
6. Create a Time Off for *Employee 1* that involves *Local Holiday* and
check the days used are computed correctly
7. Create a Time Off for *Employee 2* that involves *Local Holiday* and
check the days used are computed correctly (more days than the Time
Off of *Employee 1*)
8. Check both Employee Calendar views from the Employee form to view the
grey background on Local and Public Holidays.
If you have installed Attendances and Contracts apps, and create
attenances for both employees on the *Local Holiday* you can also check
Extra Hours are computed correctly in both employees.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/hr-holidays/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-holidays/issues/new?body=module:%20resource_leaves_geographic%0Aversion:%2016.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
-------
* Moduon
Contributors
------------
- Eduardo de Miguel (`Moduon <https://www.moduon.team/>`__)
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.
.. |maintainer-Shide| image:: https://github.com/Shide.png?size=40px
:target: https://github.com/Shide
:alt: Shide
.. |maintainer-rafaelbn| image:: https://github.com/rafaelbn.png?size=40px
:target: https://github.com/rafaelbn
:alt: rafaelbn
Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-Shide| |maintainer-rafaelbn|
This module is part of the `OCA/hr-holidays <https://github.com/OCA/hr-holidays/tree/16.0/resource_leaves_geographic>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1,23 @@
# Copyright 2024 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
{
"name": "Resource Leaves Geographic",
"summary": "Add geographic State to Resource Calendar Leaves",
"version": "16.0.1.0.1",
"development_status": "Alpha",
"category": "Human Resources/Time Off",
"website": "https://github.com/OCA/hr-holidays",
"author": "Moduon, Odoo Community Association (OCA)",
"maintainers": ["Shide", "rafaelbn"],
"license": "LGPL-3",
"application": False,
"installable": True,
"depends": [
"resource",
"hr_holidays",
],
"data": [
"views/resource_calendar_leaves_views.xml",
],
}

View file

@ -0,0 +1,39 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * resource_leaves_geographic
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.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: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_hr_employee
msgid "Employee"
msgstr "Zaposleni"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar_leaves
msgid "Resource Time Off Detail"
msgstr "Detalji odsustva resursa"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar
msgid "Resource Working Time"
msgstr "Radno vrijeme resursa"
#. module: resource_leaves_geographic
#: model:ir.model.fields,field_description:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States"
msgstr "Status"
#. module: resource_leaves_geographic
#: model:ir.model.fields,help:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States for which this leave is applicable"
msgstr "Stanja za koja je ovo odsustvo primjenjivo"

View file

@ -0,0 +1,38 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * resource_leaves_geographic
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-31 07:50+0000\n"
"PO-Revision-Date: 2024-07-31 09:52+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.4.4\n"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar_leaves
msgid "Resource Time Off Detail"
msgstr "Detalle de las ausencias del recurso"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar
msgid "Resource Working Time"
msgstr "Tiempo de Trabajo de Recursos"
#. module: resource_leaves_geographic
#: model:ir.model.fields,field_description:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States"
msgstr "Estados"
#. module: resource_leaves_geographic
#: model:ir.model.fields,help:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States for which this leave is applicable"
msgstr "Estados para los que se aplica esta ausencia"

View file

@ -0,0 +1,42 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * resource_leaves_geographic
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-08-26 12:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.6.2\n"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_hr_employee
msgid "Employee"
msgstr "Dipendente"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar_leaves
msgid "Resource Time Off Detail"
msgstr "Dettaglio ferie risorsa"
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar
msgid "Resource Working Time"
msgstr "Orario lavoro risorsa"
#. module: resource_leaves_geographic
#: model:ir.model.fields,field_description:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States"
msgstr "Stati"
#. module: resource_leaves_geographic
#: model:ir.model.fields,help:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States for which this leave is applicable"
msgstr "Stati per i quali è applicabile questa assenza"

View file

@ -0,0 +1,39 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * resource_leaves_geographic
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.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: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_hr_employee
msgid "Employee"
msgstr ""
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar_leaves
msgid "Resource Time Off Detail"
msgstr ""
#. module: resource_leaves_geographic
#: model:ir.model,name:resource_leaves_geographic.model_resource_calendar
msgid "Resource Working Time"
msgstr ""
#. module: resource_leaves_geographic
#: model:ir.model.fields,field_description:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States"
msgstr ""
#. module: resource_leaves_geographic
#: model:ir.model.fields,help:resource_leaves_geographic.field_resource_calendar_leaves__state_ids
msgid "States for which this leave is applicable"
msgstr ""

View file

@ -0,0 +1,3 @@
from . import resource_calendar_leaves
from . import resource_calendar
from . import hr_employee

View file

@ -0,0 +1,51 @@
# Copyright 2024 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
from datetime import datetime, time
from dateutil.rrule import DAILY, rrule
from pytz import UTC
from odoo import fields, models
class HrEmployee(models.Model):
_inherit = "hr.employee"
def _get_unusual_days(self, date_from, date_to=None):
"""Get the geographical unusual days belongs to employees"""
res = super()._get_unusual_days(date_from, date_to=date_to)
def dt_combiner(dt, tx):
"""Return a datetime object with the date converted to datetime
:param dt: date string
:param tx: time.min or time.max
"""
return datetime.combine(fields.Date.from_string(dt), tx).replace(tzinfo=UTC)
calendars = (
self.mapped("resource_calendar_id") or self.env.company.resource_calendar_id
)
state_interval_map = calendars._get_general_time_off_intervals_by_state(
domain=[
("state_ids", "in", self.mapped("address_id.state_id").ids),
("date_from", "<=", dt_combiner(date_to, time.max)),
("date_to", ">=", dt_combiner(date_from, time.min)),
],
any_calendar=False,
)
local_leave_days = set()
for state_interval_map in state_interval_map.values():
for start, end, _rcl in state_interval_map:
local_leave_days.update(
{
fields.Date.to_string(day.date())
for day in rrule(DAILY, start.date(), until=end.date())
}
)
for day in res.keys():
if day in local_leave_days:
res[day] = True
return res

View file

@ -0,0 +1,87 @@
# Copyright 2024 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
from collections import defaultdict
from odoo import fields, models
from odoo.addons.resource.models.resource import Intervals
class ResourceCalendar(models.Model):
_inherit = "resource.calendar"
def _get_general_time_off_intervals_by_state(self, domain=None, any_calendar=False):
"""Get a map of State to Intervals of leaves for the given domain."""
domain = domain or []
# Respect the any_calendar option
if not any_calendar:
domain = [("calendar_id", "in", self.ids + [False])] + domain
# Ensure that the leaves are not related to a specific resource
domain = [("resource_id", "=", False)] + domain
# Iterate all matching leaves
state_interval_map = defaultdict(Intervals)
for res_cal_leave in self.env["resource.calendar.leaves"].search(domain):
# Convert to aware datetime with user timezone
dttf = fields.Datetime.context_timestamp(
res_cal_leave, res_cal_leave.date_from
)
dttt = fields.Datetime.context_timestamp(
res_cal_leave, res_cal_leave.date_to
)
# Add the interval to the corresponding State or False if no state
if res_cal_leave.state_ids:
for state in res_cal_leave.state_ids:
state_interval_map[state.id] |= Intervals(
[(dttf, dttt, res_cal_leave)]
)
else:
state_interval_map[False] |= Intervals([(dttf, dttt, res_cal_leave)])
return state_interval_map
def _leave_intervals_batch(
self, start_dt, end_dt, resources=None, domain=None, tz=None, any_calendar=False
):
# All interval batches (with/out State)
res = super()._leave_intervals_batch(
start_dt,
end_dt,
resources=resources,
domain=domain,
tz=tz,
any_calendar=any_calendar,
)
# Overwrite the result if resources are specified, but only with
# the global leaves (skipping the local leaves) using the domain
for resource in resources or []:
res.update(
super()._leave_intervals_batch(
start_dt,
end_dt,
resources=resource,
domain=[("state_ids", "=", False)], # Force global leaves
tz=tz,
any_calendar=any_calendar,
)
)
# Get Local interval batches by State
state_interval_map = self._get_general_time_off_intervals_by_state(
domain=domain, any_calendar=any_calendar
)
# Post-process generated intervals
for resource_id in res.keys():
if not resource_id:
# If no resource is specified, only consider Global leaves
res[resource_id] = state_interval_map[False]
else:
# If resource is specified, add Local Leaves to the result if
# the State of its Work Address has Local leaves
resource_state_id = (
self.env["hr.employee"]
.sudo()
.search([("resource_id", "=", resource_id)], limit=1)
.address_id.state_id.id
)
if resource_state_id in state_interval_map:
res[resource_id] |= state_interval_map[resource_state_id]
return res

View file

@ -0,0 +1,14 @@
# Copyright 2024 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
from odoo import fields, models
class ResourceCalendarLeaves(models.Model):
_inherit = "resource.calendar.leaves"
state_ids = fields.Many2many(
comodel_name="res.country.state",
string="States",
help="States for which this leave is applicable",
)

View file

@ -0,0 +1,3 @@
This module was developed because in order to differentiate local Employee holidays, they must be added to their calendars instead of being able to mark them on the general company calendar.
This will be useful for you if you want to be able to create holidays by State in the company calendar and have them automatically applied to all employees based on their workplace.

View file

@ -0,0 +1 @@
- Eduardo de Miguel ([Moduon](https://www.moduon.team/))

View file

@ -0,0 +1,7 @@
This module extends the functionality of Public Holidays to support States and allow you to define Local Holidays more easily in the Company Calendar.
Shows on Time Off all the holidays (with/without State) in the Public Holidays section.
Public Holidays (without State) always will have grey background.
Local holidays displayed with a grey background in the calendar view belong to the Employee currently viewing the calendar or to the single Employee selected from the Employee Form view.
This module is compatible with Attendances and Contracts (but those modules are not required).

View file

@ -0,0 +1,12 @@
To use this module, you need to:
1. Go to Time Off app > Configuration > Public Holidays
2. Create a Public Holiday without State with name *Local Holiday*
3. Create an *Employee 1* and set his Work Address in the same State than your *Local Holiday*
4. Create an *Employee 2* and set his Work Address in other State than your *Local Holiday*
5. Go to Time Off > Overview and check the grey background is only on *Employee 1* on the days used in *Local Holiday*
6. Create a Time Off for *Employee 1* that involves *Local Holiday* and check the days used are computed correctly
7. Create a Time Off for *Employee 2* that involves *Local Holiday* and check the days used are computed correctly (more days than the Time Off of *Employee 1*)
8. Check both Employee Calendar views from the Employee form to view the grey background on Local and Public Holidays.
If you have installed Attendances and Contracts apps, and create attenances for both employees on the *Local Holiday* you can also check Extra Hours are computed correctly in both employees.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,475 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Resource Leaves Geographic</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="resource-leaves-geographic">
<h1 class="title">Resource Leaves Geographic</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:19175838a39febb826f0243ad4ae704b07ae0ef0ec132b3c57fae3cb8b1693b2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/hr-holidays/tree/16.0/resource_leaves_geographic"><img alt="OCA/hr-holidays" src="https://img.shields.io/badge/github-OCA%2Fhr--holidays-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/hr-holidays-16-0/hr-holidays-16-0-resource_leaves_geographic"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/hr-holidays&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module extends the functionality of Public Holidays to support
States and allow you to define Local Holidays more easily in the Company
Calendar.</p>
<p>Shows on Time Off all the holidays (with/without State) in the Public
Holidays section. Public Holidays (without State) always will have grey
background. Local holidays displayed with a grey background in the
calendar view belong to the Employee currently viewing the calendar or
to the single Employee selected from the Employee Form view.</p>
<p>This module is compatible with Attendances and Contracts (but those
modules are not required).</p>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
<a class="reference external" href="https://odoo-community.org/page/development-status">More details on development status</a></p>
</div>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#use-cases-context" id="toc-entry-1">Use Cases / Context</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="use-cases-context">
<h1><a class="toc-backref" href="#toc-entry-1">Use Cases / Context</a></h1>
<p>This module was developed because in order to differentiate local
Employee holidays, they must be added to their calendars instead of
being able to mark them on the general company calendar.</p>
<p>This will be useful for you if you want to be able to create holidays by
State in the company calendar and have them automatically applied to all
employees based on their workplace.</p>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>To use this module, you need to:</p>
<ol class="arabic simple">
<li>Go to Time Off app &gt; Configuration &gt; Public Holidays</li>
<li>Create a Public Holiday without State with name <em>Local Holiday</em></li>
<li>Create an <em>Employee 1</em> and set his Work Address in the same State
than your <em>Local Holiday</em></li>
<li>Create an <em>Employee 2</em> and set his Work Address in other State than
your <em>Local Holiday</em></li>
<li>Go to Time Off &gt; Overview and check the grey background is only on
<em>Employee 1</em> on the days used in <em>Local Holiday</em></li>
<li>Create a Time Off for <em>Employee 1</em> that involves <em>Local Holiday</em> and
check the days used are computed correctly</li>
<li>Create a Time Off for <em>Employee 2</em> that involves <em>Local Holiday</em> and
check the days used are computed correctly (more days than the Time
Off of <em>Employee 1</em>)</li>
<li>Check both Employee Calendar views from the Employee form to view the
grey background on Local and Public Holidays.</li>
</ol>
<p>If you have installed Attendances and Contracts apps, and create
attenances for both employees on the <em>Local Holiday</em> you can also check
Extra Hours are computed correctly in both employees.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/hr-holidays/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/hr-holidays/issues/new?body=module:%20resource_leaves_geographic%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Moduon</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Eduardo de Miguel (<a class="reference external" href="https://www.moduon.team/">Moduon</a>)</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/Shide"><img alt="Shide" src="https://github.com/Shide.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/rafaelbn"><img alt="rafaelbn" src="https://github.com/rafaelbn.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/hr-holidays/tree/16.0/resource_leaves_geographic">OCA/hr-holidays</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
from . import test_resource_calendar_leaves

View file

@ -0,0 +1,88 @@
# Copyright 2024 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
from odoo.tests.common import TransactionCase
from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT
class TestResourceCalendarLeaves(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT))
cls.trcl_State = cls.env["res.country.state"].create(
{
"name": "TRCL State",
"code": "TRCL",
"country_id": cls.env.user.company_id.country_id.id,
}
)
cls.partner = cls.env["res.partner"].create({"name": "TRCL Partner"})
cls.employee = cls.env["hr.employee"].create(
{"name": "TRCL Employee 1", "address_id": cls.partner.id}
)
cls.global_leave = cls.env["resource.calendar.leaves"].create(
{
"name": "Global Leave",
"date_from": "2024-07-01 00:00:00",
"date_to": "2024-07-01 23:59:59",
"state_ids": None,
}
)
cls.local_leave = cls.env["resource.calendar.leaves"].create(
{
"name": "Local Leave",
"date_from": "2024-07-02 00:00:00",
"date_to": "2024-07-02 23:59:59",
"state_ids": [(6, 0, cls.trcl_State.ids)],
}
)
cls.timeoff_type = cls.env["hr.leave.type"].create(
{
"name": "TRCL Time Off",
"leave_validation_type": "no_validation",
"requires_allocation": "no",
}
)
def _create_leave(self):
leave = self.env["hr.leave"].create(
{
"name": "TRCL Leave",
"date_from": "2024-06-28 00:00:00",
"date_to": "2024-07-02 23:59:59",
"employee_id": self.employee.id,
"holiday_status_id": self.timeoff_type.id,
}
)
if leave.state != "validate":
leave.action_confirm()
self.assertEqual(leave.state, "validate")
return leave
def test_leave_partner_without_state(self):
leave = self._create_leave()
# Leave does not take in consideration State
self.assertEqual(leave.number_of_days_display, 2.0)
def test_leave_partner_with_state(self):
self.partner.state_id = self.trcl_State.id
leave = self._create_leave()
# Leave takes in consideration State
self.assertEqual(leave.number_of_days_display, 1.0)
def test_unusual_days_without_state(self):
unusual_days = self.employee._get_unusual_days(
"2024-07-01", date_to="2024-07-02"
)
self.assertTrue(unusual_days["2024-07-01"])
self.assertFalse(unusual_days["2024-07-02"])
def test_unusual_days_with_state(self):
self.partner.state_id = self.trcl_State.id
unusual_days = self.employee._get_unusual_days(
"2024-07-01", date_to="2024-07-02"
)
self.assertTrue(unusual_days["2024-07-01"])
self.assertTrue(unusual_days["2024-07-02"])

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2024 Moduon Team S.L.
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) -->
<data>
<record id="resource_calendar_leave_tree" model="ir.ui.view">
<field name="name">resource.calendar.leaves.state.tree</field>
<field name="model">resource.calendar.leaves</field>
<field name="inherit_id" ref="resource.resource_calendar_leave_tree" />
<field name="arch" type="xml">
<xpath expr="//field[@name='company_id']" position="after">
<field
name="state_ids"
widget="many2many_tags"
options="{'no_create': True}"
/>
</xpath>
</field>
</record>
<record id="resource_calendar_leave_form" model="ir.ui.view">
<field name="name">resource.calendar.leaves.state.form</field>
<field name="model">resource.calendar.leaves</field>
<field name="inherit_id" ref="resource.resource_calendar_leave_form" />
<field name="arch" type="xml">
<xpath expr="//group[@name='leave_dates']" position="inside">
<field
name="state_ids"
widget="many2many_tags"
options="{'no_create': True}"
/>
</xpath>
</field>
</record>
<record id="view_resource_calendar" model="ir.ui.view">
<field name="name">resource.calendar.leaves.state.calendar</field>
<field name="model">resource.calendar.leaves</field>
<field name="inherit_id" ref="resource.view_resource_calendar" />
<field name="arch" type="xml">
<xpath expr="//field[@name='company_id']" position="after">
<field name="state_ids" widget="many2many_tags" />
</xpath>
</field>
</record>
<record id="view_resource_calendar_leaves_search" model="ir.ui.view">
<field name="name">resource.calendar.leaves.state.search</field>
<field name="model">resource.calendar.leaves</field>
<field name="inherit_id" ref="resource.view_resource_calendar_leaves_search" />
<field name="arch" type="xml">
<xpath expr="//field[@name='company_id']" position="after">
<field name="state_ids" />
</xpath>
</field>
</record>
</data>