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,44 @@
# Employee Calendar Planning
Odoo addon: hr_employee_calendar_planning
## Installation
```bash
pip install odoo-bringout-oca-hr-hr_employee_calendar_planning
```
## Dependencies
This addon depends on:
- hr
## Manifest Information
- **Name**: Employee Calendar Planning
- **Version**: 16.0.1.1.11
- **Category**: Human Resources
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/hr](https://github.com/OCA/hr) branch 16.0, addon `hr_employee_calendar_planning`.
## License
This package maintains the original AGPL-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 Hr_employee_calendar_planning Module - hr_employee_calendar_planning
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 hr_employee_calendar_planning. 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,5 @@
# Dependencies
This addon depends on:
- [hr](../../odoo-bringout-oca-ocb-hr)

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 hr_employee_calendar_planning or install in UI.

View file

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

View file

@ -0,0 +1,14 @@
# Models
Detected core models and extensions in hr_employee_calendar_planning.
```mermaid
classDiagram
class hr_employee_calendar
class hr_employee
class resource_calendar
```
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: hr_employee_calendar_planning. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon hr_employee_calendar_planning
- License: LGPL-3

View file

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

View file

@ -0,0 +1,34 @@
# Security
Access control and security definitions in hr_employee_calendar_planning.
## Access Control Lists (ACLs)
Model access permissions defined in:
- **[ir.model.access.csv](../hr_employee_calendar_planning/security/ir.model.access.csv)**
- 2 model access rules
## Record Rules
Row-level security rules defined in:
```mermaid
graph TB
subgraph "Security Layers"
A[Users] --> B[Groups]
B --> C[Access Control Lists]
C --> D[Models]
B --> E[Record Rules]
E --> F[Individual Records]
end
```
Security files overview:
- **[ir.model.access.csv](../hr_employee_calendar_planning/security/ir.model.access.csv)**
- Model access permissions (CRUD rights)
Notes
- Access Control Lists define which groups can access which models
- Record Rules provide row-level security (filter records by user/group)
- Security groups organize users and define permission sets
- All security is enforced at the ORM level by Odoo

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 hr_employee_calendar_planning
```

View file

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

View file

@ -0,0 +1,144 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
==========================
Employee Calendar Planning
==========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:04cec64bc7a93390d0b20f593c1458ff026f418de1de8ce4bddbefd630a1acb7
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/license-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-lightgray.png?logo=github
:target: https://github.com/OCA/hr/tree/16.0/hr_employee_calendar_planning
:alt: OCA/hr
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/hr-16-0/hr-16-0-hr_employee_calendar_planning
: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&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows to manage employee working time with profiles by date
intervals.
The profiles are regular working time calendars, but they are treated as
master ones here, allowing you to compose complexes working times by dates.
Under the hook, a unique working time is created for each employee with the
proper composition for not affecting the rest of the functionality linked to
this model.
**Table of contents**
.. contents::
:local:
Installation
============
During the installation of the module, current working times are split by
start/end dates for having consistent data, and the potential new composed
calendar planning is saved instead on the employee.
Configuration
=============
#. Go to *Employees > Employees*.
#. Open or create a new one.
#. On the "Work Information" tab, fill the section "Working Hours" with:
* Starting date (optional).
* Ending date (optional).
* Working time to apply during that date interval.
Known issues / Roadmap
======================
* Add a wizard for generating next year calendar planning based on current one
in batch.
* Add constraint for avoiding planning lines overlapping.
* Avoid the regeneration of whole private calendars each time a change is
detected.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/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/OCA/hr/issues/new?body=module:%20hr_employee_calendar_planning%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
~~~~~~~
* Tecnativa
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Víctor Martínez
* `Creu Blanca <https://www.creu-blanca.es/>`_:
* Jaime Arroyo
* `ForgeFlow <https://www.forgeflow.com/>`_:
* Jordi Ballester Alomar (jordi.ballester@forgeflow.com)
* Nattapong W. <aphon61bank@gmail.com>
* `Pesol <https://www.pesol.es>`__:
* Pedro Evaristo Gonzalez Sanchez <pedro.gonzalez@pesol.es>
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-victoralmau| image:: https://github.com/victoralmau.png?size=40px
:target: https://github.com/victoralmau
:alt: victoralmau
.. |maintainer-pedrobaeza| image:: https://github.com/pedrobaeza.png?size=40px
:target: https://github.com/pedrobaeza
:alt: pedrobaeza
Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-victoralmau| |maintainer-pedrobaeza|
This module is part of the `OCA/hr <https://github.com/OCA/hr/tree/16.0/hr_employee_calendar_planning>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1,4 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models
from .hooks import post_init_hook

View file

@ -0,0 +1,19 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Employee Calendar Planning",
"version": "16.0.1.1.11",
"category": "Human Resources",
"website": "https://github.com/OCA/hr",
"author": "Tecnativa,Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"depends": ["hr"],
"data": [
"security/ir.model.access.csv",
"views/hr_employee_views.xml",
"views/resource_calendar_views.xml",
],
"post_init_hook": "post_init_hook",
"maintainers": ["victoralmau", "pedrobaeza"],
}

View file

@ -0,0 +1,71 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from collections import defaultdict
from odoo import SUPERUSER_ID, api
def post_init_hook(cr, registry, employees=None):
"""Split current calendars by date ranges and assign new ones for
having proper initial data.
"""
env = api.Environment(cr, SUPERUSER_ID, {})
if not employees:
employees = env["hr.employee"].search([])
calendars = employees.mapped("resource_calendar_id")
calendar_obj = env["resource.calendar"]
line_obj = env["resource.calendar.attendance"]
groups = line_obj.read_group(
[("calendar_id", "in", calendars.ids)],
["calendar_id", "date_from", "date_to"],
["calendar_id", "date_from:day", "date_to:day"],
lazy=False,
)
calendar_mapping = defaultdict(list)
for group in groups:
calendar = calendar_obj.browse(group["calendar_id"][0])
lines = line_obj.search(group["__domain"])
if len(calendar.attendance_ids) == len(lines):
# Don't alter calendar, as it's the same
new_calendar = calendar
else:
name = calendar.name + " {}-{}".format(
lines[0].date_from,
lines[0].date_to,
)
attendances = []
for line in lines:
data = line.copy_data({"date_from": False, "date_to": False})[0]
data.pop("calendar_id")
attendances.append((0, 0, data))
new_calendar = calendar_obj.create(
{"name": name, "attendance_ids": attendances}
)
calendar_mapping[calendar].append(
(lines[0].date_from, lines[0].date_to, new_calendar),
)
for employee in employees.filtered("resource_calendar_id"):
calendar_lines = []
for data in calendar_mapping[employee.resource_calendar_id]:
calendar_lines.append(
(
0,
0,
{
"date_start": data[0],
"date_end": data[1],
"calendar_id": data[2].id,
},
)
)
# Extract employee's existing leaves so they are passed to the new
# automatic calendar.
employee.calendar_ids = calendar_lines
employee.resource_calendar_id.active = False
# Now the automatic calendar has been created, so we link the
# leaves to that one so they count correctly.
leaves = employee.resource_calendar_id.leave_ids.filtered(
lambda x: x.resource_id == employee.resource_id
)
leaves.write({"calendar_id": employee.resource_calendar_id.id})

View file

@ -0,0 +1,150 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
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: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr "Aktivan"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr "Automatski generiraj"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr "Automatski generirani kalendar za zaposlenika"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr "Planiranje kalendara"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr "Preduzeće"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr "Datum završetka treba biti veći od datuma početka"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr "Zaposleni"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr "Kalendar zaposlenika"
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr "Kalendari zaposlenika"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr "Datum završetka"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr "ID"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr "Zadnje mijenjano"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr "Zadnji ažurirao"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr "Radno vrijeme resursa"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr "Početni datum"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr "Radno Vrijeme"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr "Ne možete kreirati zaposlenike bez ikakvog kalendara."

View file

@ -0,0 +1,163 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2022-03-21 14:17+0000\n"
"Last-Translator: Noel estudillo <noelestudilloviera@gmail.com>\n"
"Language-Team: none\n"
"Language: ca\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 4.3.2\n"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr "Actiu"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr "Generació automàtica"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr "Horari autogenerat per a l'empleat"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr "Pla d'horari"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr "Companyia"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr "Creat per"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr "Creat el"
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr "La data de fi ha de ser més gran que la d'inici"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr "Nom a mostrar"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr "Empleat"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr "Horari de l'empleat"
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr "Data de finalització"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr "ID"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
"Si el camp actiu està definit com a fals, us permetrà ocultar el temps de "
"treball sense eliminar-lo."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr "Darrera modificació el"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr "Darrera modificació per"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr "Darrera modificació el"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr "Temps de treball"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr "Data d'Inici"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr "Temps de treball"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr ""
#, python-format
#~ msgid "%s is used in %s employee(s) related to another company."
#~ msgstr "%s s'utilitza en %s empleats relacionats amb una altra empresa."
#, python-format
#~ msgid "%s is used in %s employee(s). You should change them first."
#~ msgstr "%s s'utilitza en %s empleat(s). Primer els hauries de canviar."

View file

@ -0,0 +1,151 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: ca_ES\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"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr ""
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr ""

View file

@ -0,0 +1,151 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: de\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"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr ""
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr ""

View file

@ -0,0 +1,160 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-08-29 06:53+0000\n"
"PO-Revision-Date: 2023-11-27 19:36+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\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: Weblate 4.17\n"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
"%(item_name)s está usado en %(total_items)s empleado/a(s) relacionado/a(s) "
"con otra compañía."
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
"%(item_name)s está usado en %(total_items)s empleado(s). Debería cambiarlo "
"primero."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr "Activo"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr "Generación Automática"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr "Horario autogenerado para el empleado"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr "Plan de Horario"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr "Compañía"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr "Creado el"
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr "La fecha de fin debe ser mayor que la de inicio"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr "Nombre a mostrar"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr "Empleado"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr "Horario del Empleado"
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr "Calendarios de los empleados"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr "Fecha de finalización"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr "ID"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
"Si el campo activo se establece en falso, le permitirá ocultar el tiempo de "
"trabajo sin eliminarlo."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr "Última modificación el"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr "Última modificación por"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr "Última modificación el"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr "Tiempo de trabajo"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr "Fecha de Inicio"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr "Tiempo de Trabajo"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr "No puede crear empleados sin ningún calendario."

View file

@ -0,0 +1,163 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2022-08-05 01:07+0000\n"
"Last-Translator: Nicolas Rodriguez Sande <nicolasrsande@gmail.com>\n"
"Language-Team: none\n"
"Language: es_AR\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 4.3.2\n"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr "Activo"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr "Autogenerar"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr "Calendario autogenerado para el empleado"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr "Planeamiento de calendario"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr "Empresa"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr "Creado en"
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr "Fecha final debe ser posterior a la fecha inicial"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr "Nombre para mostrar"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr "Empleado"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr "Calendario del empleado"
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr "Fecha hasta"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr "ID"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
"Si el campo activo es falso, te permite ocultar este registro sin removerlo."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr "Última modificación en"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr "Última actualización en"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr "Tiempo de trabajo del recurso"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr "Fecha inicio"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr "Tiempo de trabajo"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr "No puedes crear empleados sin asignarles ningún calendario."
#, python-format
#~ msgid "%s is used in %s employee(s) related to another company."
#~ msgstr ""
#~ "%s está siendo usada en %s empleados(s) relacionados con otra compañía."
#, python-format
#~ msgid "%s is used in %s employee(s). You should change them first."
#~ msgstr "%s está siendo usado en los empleados %s. Debes cambiarlo primero."

View file

@ -0,0 +1,155 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2021-05-14 17:47+0000\n"
"Last-Translator: Yves Le Doeuff <yld@alliasys.fr>\n"
"Language-Team: none\n"
"Language: fr\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 4.3.2\n"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr "Actif"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr "Calendrier généré automatiquement pour les employés"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr "Calendrier planning"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr "Créé le"
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr "La date de fin doit être postérieure à la date de début"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr "Employé"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr "Calendrier de l'employé"
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr "Date de fin"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
"Si le champ actif est défini sur Faux, il vous permettra de masquer la durée "
"de travail sans la supprimer."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr "Horaire de travail de la ressource"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr "Date de début"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr "Horaire de travail"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr ""

View file

@ -0,0 +1,150 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
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: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr ""
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr ""
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr ""
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr ""

View file

@ -0,0 +1,159 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * hr_employee_calendar_planning
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-11-30 15:37+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 4.17\n"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s) related to another "
"company."
msgstr ""
"L'elemento %(item_name)s è utilizzato in %(total_items)s dipendenti relativo "
"ad un'altra azienda."
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/resource_calendar.py:0
#, python-format
msgid ""
"%(item_name)s is used in %(total_items)s employee(s).You should change them "
"first."
msgstr ""
"L'elemento %(item_name)s è utilizzato in %(total_items)s dipendenti. Bisogna "
"prima modificarli."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__active
msgid "Active"
msgstr "Attiva"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__auto_generate
msgid "Auto Generate"
msgstr "Auto generata"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "Auto generated calendar for employee"
msgstr "Calendario auto generato per dipendente"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee__calendar_ids
msgid "Calendar planning"
msgstr "Pianificazione calendario"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__company_id
msgid "Company"
msgstr "Azienda"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_uid
msgid "Created by"
msgstr "Creato da"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__create_date
msgid "Created on"
msgstr "Creato il"
#. module: hr_employee_calendar_planning
#: model:ir.model.constraint,message:hr_employee_calendar_planning.constraint_hr_employee_calendar_date_consistency
msgid "Date end should be higher than date start"
msgstr "La data fine deve essere successiva alla data inizio"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__display_name
msgid "Display Name"
msgstr "Nome visualizzato"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__employee_id
msgid "Employee"
msgstr "Dipendente"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_hr_employee_calendar
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_resource_calendar__employee_calendar_ids
msgid "Employee Calendar"
msgstr "Calendario dipendente"
#. module: hr_employee_calendar_planning
#: model_terms:ir.ui.view,arch_db:hr_employee_calendar_planning.resource_calendar_form
msgid "Employee Calendars"
msgstr "Calendari dipendente"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_end
msgid "End Date"
msgstr "Data fine"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__id
msgid "ID"
msgstr "ID"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,help:hr_employee_calendar_planning.field_resource_calendar__active
msgid ""
"If the active field is set to false, it will allow you to hide the Working "
"Time without removing it."
msgstr ""
"Se il campo attivo è impostato a falso, consente di nascondere il tempo "
"lavorato senza eliminarlo."
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar____last_update
msgid "Last Modified on"
msgstr "Ultima modifica il"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_uid
msgid "Last Updated by"
msgstr "Ultimo aggiornamento di"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__write_date
msgid "Last Updated on"
msgstr "Ultimo aggiornamento il"
#. module: hr_employee_calendar_planning
#: model:ir.model,name:hr_employee_calendar_planning.model_resource_calendar
msgid "Resource Working Time"
msgstr "Orario lavoro risorsa"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__date_start
msgid "Start Date"
msgstr "Data inizio"
#. module: hr_employee_calendar_planning
#: model:ir.model.fields,field_description:hr_employee_calendar_planning.field_hr_employee_calendar__calendar_id
msgid "Working Time"
msgstr "Orario lavoro"
#. module: hr_employee_calendar_planning
#. odoo-python
#: code:addons/hr_employee_calendar_planning/models/hr_employee.py:0
#, python-format
msgid "You can not create employees without any calendar."
msgstr "Non è possibile creare un dipendente senza un calendario."

View file

@ -0,0 +1,2 @@
from . import hr_employee
from . import resource_calendar

View file

@ -0,0 +1,241 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# Copyright 2022-2023 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools import config
SECTION_LINES = [
(
0,
0,
{
"name": "Even week",
"dayofweek": "0",
"sequence": "0",
"hour_from": 0,
"day_period": "morning",
"week_type": "0",
"hour_to": 0,
"display_type": "line_section",
},
),
(
0,
0,
{
"name": "Odd week",
"dayofweek": "0",
"sequence": "25",
"hour_from": 0,
"day_period": "morning",
"week_type": "1",
"hour_to": 0,
"display_type": "line_section",
},
),
]
class HrEmployee(models.Model):
_inherit = "hr.employee"
calendar_ids = fields.One2many(
comodel_name="hr.employee.calendar",
inverse_name="employee_id",
string="Calendar planning",
copy=True,
)
@api.model
def default_get(self, fields):
"""Set calendar_ids default value to cover all use cases."""
vals = super().default_get(fields)
if "calendar_ids" in fields and not vals.get("calendar_ids"):
vals["calendar_ids"] = [
(0, 0, {"calendar_id": self.env.company.resource_calendar_id.id}),
]
return vals
def _regenerate_calendar(self):
self.ensure_one()
vals_list = []
two_weeks = bool(
self.calendar_ids.mapped("calendar_id").filtered("two_weeks_calendar")
)
if self.resource_id.calendar_id.auto_generate:
self.resource_calendar_id.attendance_ids.unlink()
self.resource_calendar_id.two_weeks_calendar = two_weeks
seq = 0
for week in ["0", "1"] if two_weeks else ["0"]:
if two_weeks:
section_vals = SECTION_LINES[int(week)]
section_vals[2]["sequence"] = seq
vals_list.append(section_vals)
seq += 1
for line in self.calendar_ids:
if line.calendar_id.two_weeks_calendar:
attendances = line.calendar_id.attendance_ids.filtered(
lambda x: x.week_type == week
)
else:
attendances = line.calendar_id.attendance_ids
for attendance_line in attendances:
if attendance_line.display_type == "line_section":
continue
data = attendance_line.copy_data(
{
"calendar_id": self.resource_calendar_id.id,
"date_from": line.date_start,
"date_to": line.date_end,
"week_type": week if two_weeks else False,
"sequence": seq,
}
)[0]
seq += 1
vals_list.append((0, 0, data))
# Autogenerate
if not self.resource_id.calendar_id.auto_generate:
self.resource_id.calendar_id = (
self.env["resource.calendar"]
.create(
{
"active": False,
"company_id": self.company_id.id,
"auto_generate": True,
"name": _("Auto generated calendar for employee")
+ " %s" % self.name,
"attendance_ids": vals_list,
"two_weeks_calendar": two_weeks,
"tz": self.tz, # take employee timezone as default
}
)
.id
)
else:
self.resource_calendar_id.attendance_ids = vals_list
# Set the hours per day to the last (top date end) calendar line to apply
if self.calendar_ids:
self.resource_id.calendar_id.hours_per_day = self.calendar_ids[
0
].calendar_id.hours_per_day
# set global leaves
self.copy_global_leaves()
def copy_global_leaves(self):
self.ensure_one()
leave_ids = []
for calendar in self.calendar_ids:
global_leaves = calendar.calendar_id.global_leave_ids
if calendar.date_start:
global_leaves = global_leaves.filtered(
lambda x: x.date_from.date() >= calendar.date_start
)
if calendar.date_end:
global_leaves = global_leaves.filtered(
lambda x: x.date_to.date() <= calendar.date_end
)
leave_ids += global_leaves.ids
vals = [
leave.copy_data({"calendar_id": self.resource_id.calendar_id.id})[0]
for leave in self.env["resource.calendar.leaves"].search(
[("id", "in", leave_ids)], order="date_from asc"
)
]
existing_leaves_mapping = {
e.date_from: e for e in self.resource_id.calendar_id.global_leave_ids
}
requested_create_dates = [(e.get("date_from"), e.get("date_to")) for e in vals]
new_vals = [
v
for v in vals
if not (
v.get("date_from") in existing_leaves_mapping
and v.get("date_to")
== existing_leaves_mapping[v.get("date_from")].date_to
)
]
to_unlink = self.resource_id.calendar_id.global_leave_ids.filtered(
lambda x: (x.date_from, x.date_to) not in requested_create_dates
)
to_unlink.unlink()
return self.env["resource.calendar.leaves"].create(new_vals).ids
def regenerate_calendar(self):
for item in self:
item._regenerate_calendar()
def copy(self, default=None):
self.ensure_one()
new = super().copy(default)
# Define a good main calendar for being able to regenerate it later
new.resource_id.calendar_id = fields.first(new.calendar_ids).calendar_id
new.filtered("calendar_ids").regenerate_calendar()
return new
@api.model_create_multi
def create(self, vals_list):
res = super().create(vals_list)
# Avoid creating an employee without calendars
if (
not self.env.context.get("skip_employee_calendars_required")
and not config["test_enable"]
and not self.env.context.get("install_mode")
and res.filtered(lambda x: not x.calendar_ids)
):
raise UserError(_("You can not create employees without any calendar."))
res.filtered("calendar_ids").regenerate_calendar()
return res
class HrEmployeeCalendar(models.Model):
_name = "hr.employee.calendar"
_description = "Employee Calendar"
_order = "date_end desc"
date_start = fields.Date(
string="Start Date",
)
date_end = fields.Date(
string="End Date",
)
employee_id = fields.Many2one(
comodel_name="hr.employee", string="Employee", required=True, ondelete="cascade"
)
company_id = fields.Many2one(related="employee_id.company_id")
calendar_id = fields.Many2one(
comodel_name="resource.calendar",
string="Working Time",
required=True,
check_company=True,
ondelete="restrict",
)
_sql_constraints = [
(
"date_consistency",
"CHECK(date_start <= date_end)",
"Date end should be higher than date start",
),
]
@api.model_create_multi
def create(self, vals):
res = super().create(vals)
for employee in res.mapped("employee_id"):
employee._regenerate_calendar()
return res
def write(self, vals):
res = super().write(vals)
for employee in self.mapped("employee_id"):
employee._regenerate_calendar()
return res
def unlink(self):
employees = self.mapped("employee_id")
res = super().unlink()
for employee in employees:
employee._regenerate_calendar()
return res

View file

@ -0,0 +1,67 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class ResourceCalendar(models.Model):
_inherit = "resource.calendar"
active = fields.Boolean(default=True)
auto_generate = fields.Boolean()
employee_calendar_ids = fields.One2many("hr.employee.calendar", "calendar_id")
@api.constrains("active")
def _check_active(self):
for item in self:
total_items = self.env["hr.employee.calendar"].search_count(
[
("calendar_id", "=", item.id),
"|",
("date_end", "=", False),
("date_end", "<=", fields.Date.today()),
]
)
if total_items:
raise ValidationError(
_(
"%(item_name)s is used in %(total_items)s employee(s)."
"You should change them first.",
item_name=item.name,
total_items=total_items,
)
)
@api.constrains("company_id")
def _check_company_id(self):
for item in self.filtered("company_id"):
total_items = self.env["hr.employee.calendar"].search_count(
[
("calendar_id", "=", item.id),
("calendar_id.company_id", "=", item.company_id.id),
("employee_id.company_id", "!=", item.company_id.id),
("employee_id.company_id", "!=", False),
]
)
if total_items:
raise ValidationError(
_(
"%(item_name)s is used in %(total_items)s employee(s)"
" related to another company.",
item_name=item.name,
total_items=total_items,
)
)
def write(self, vals):
res = super().write(vals)
if "attendance_ids" in vals or "global_leave_ids" in vals:
for record in self.filtered(lambda x: not x.auto_generate):
calendars = self.env["hr.employee.calendar"].search(
[("calendar_id", "=", record.id)]
)
for employee in calendars.mapped("employee_id"):
employee._regenerate_calendar()
return res

View file

@ -0,0 +1,7 @@
#. Go to *Employees > Employees*.
#. Open or create a new one.
#. On the "Work Information" tab, fill the section "Working Hours" with:
* Starting date (optional).
* Ending date (optional).
* Working time to apply during that date interval.

View file

@ -0,0 +1,18 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Víctor Martínez
* `Creu Blanca <https://www.creu-blanca.es/>`_:
* Jaime Arroyo
* `ForgeFlow <https://www.forgeflow.com/>`_:
* Jordi Ballester Alomar (jordi.ballester@forgeflow.com)
* Nattapong W. <aphon61bank@gmail.com>
* `Pesol <https://www.pesol.es>`__:
* Pedro Evaristo Gonzalez Sanchez <pedro.gonzalez@pesol.es>

View file

@ -0,0 +1,9 @@
This module allows to manage employee working time with profiles by date
intervals.
The profiles are regular working time calendars, but they are treated as
master ones here, allowing you to compose complexes working times by dates.
Under the hook, a unique working time is created for each employee with the
proper composition for not affecting the rest of the functionality linked to
this model.

View file

@ -0,0 +1,3 @@
During the installation of the module, current working times are split by
start/end dates for having consistent data, and the potential new composed
calendar planning is saved instead on the employee.

View file

@ -0,0 +1,6 @@
* Add a wizard for generating next year calendar planning based on current one
in batch.
* Add constraint for avoiding planning lines overlapping.
* Avoid the regeneration of whole private calendars each time a change is
detected.

View file

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_employee_calendar_planning_user,access_hr_employee_calendar,model_hr_employee_calendar,base.group_user,1,0,0,0
access_hr_employee_calendar_planning_manager,access_hr_employee_calendar,model_hr_employee_calendar,hr.group_hr_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_employee_calendar_planning_user access_hr_employee_calendar model_hr_employee_calendar base.group_user 1 0 0 0
3 access_hr_employee_calendar_planning_manager access_hr_employee_calendar model_hr_employee_calendar hr.group_hr_user 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,486 @@
<!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>README.rst</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">
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="employee-calendar-planning">
<h1>Employee Calendar Planning</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:04cec64bc7a93390d0b20f593c1458ff026f418de1de8ce4bddbefd630a1acb7
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/hr/tree/16.0/hr_employee_calendar_planning"><img alt="OCA/hr" src="https://img.shields.io/badge/github-OCA%2Fhr-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/hr-16-0/hr-16-0-hr_employee_calendar_planning"><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&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 allows to manage employee working time with profiles by date
intervals.</p>
<p>The profiles are regular working time calendars, but they are treated as
master ones here, allowing you to compose complexes working times by dates.</p>
<p>Under the hook, a unique working time is created for each employee with the
proper composition for not affecting the rest of the functionality linked to
this model.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#installation" id="toc-entry-1">Installation</a></li>
<li><a class="reference internal" href="#configuration" id="toc-entry-2">Configuration</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-3">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-4">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-5">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-6">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-7">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-8">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="installation">
<h2><a class="toc-backref" href="#toc-entry-1">Installation</a></h2>
<p>During the installation of the module, current working times are split by
start/end dates for having consistent data, and the potential new composed
calendar planning is saved instead on the employee.</p>
</div>
<div class="section" id="configuration">
<h2><a class="toc-backref" href="#toc-entry-2">Configuration</a></h2>
<ol class="arabic simple">
<li>Go to <em>Employees &gt; Employees</em>.</li>
<li>Open or create a new one.</li>
<li>On the “Work Information” tab, fill the section “Working Hours” with:<ul>
<li>Starting date (optional).</li>
<li>Ending date (optional).</li>
<li>Working time to apply during that date interval.</li>
</ul>
</li>
</ol>
</div>
<div class="section" id="known-issues-roadmap">
<h2><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h2>
<ul class="simple">
<li>Add a wizard for generating next year calendar planning based on current one
in batch.</li>
<li>Add constraint for avoiding planning lines overlapping.</li>
<li>Avoid the regeneration of whole private calendars each time a change is
detected.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-4">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/hr/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/issues/new?body=module:%20hr_employee_calendar_planning%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">
<h2><a class="toc-backref" href="#toc-entry-5">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-6">Authors</a></h3>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-7">Contributors</a></h3>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
<li>Víctor Martínez</li>
</ul>
</li>
<li><a class="reference external" href="https://www.creu-blanca.es/">Creu Blanca</a>:<ul>
<li>Jaime Arroyo</li>
</ul>
</li>
<li><a class="reference external" href="https://www.forgeflow.com/">ForgeFlow</a>:<ul>
<li>Jordi Ballester Alomar (<a class="reference external" href="mailto:jordi.ballester&#64;forgeflow.com">jordi.ballester&#64;forgeflow.com</a>)</li>
<li>Nattapong W. &lt;<a class="reference external" href="mailto:aphon61bank&#64;gmail.com">aphon61bank&#64;gmail.com</a>&gt;</li>
</ul>
</li>
<li><a class="reference external" href="https://www.pesol.es">Pesol</a>:<ul>
<li>Pedro Evaristo Gonzalez Sanchez &lt;<a class="reference external" href="mailto:pedro.gonzalez&#64;pesol.es">pedro.gonzalez&#64;pesol.es</a>&gt;</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h3>
<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/victoralmau"><img alt="victoralmau" src="https://github.com/victoralmau.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/pedrobaeza"><img alt="pedrobaeza" src="https://github.com/pedrobaeza.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/hr/tree/16.0/hr_employee_calendar_planning">OCA/hr</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>
</div>
</body>
</html>

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import test_hr_employee_calendar_planning

View file

@ -0,0 +1,456 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# Copyright 2021-2023 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import exceptions, fields
from odoo.tests import common, new_test_user
from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT
from ..hooks import post_init_hook
class TestHrEmployeeCalendarPlanning(common.TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT))
resource_calendar = cls.env["resource.calendar"]
cls.calendar1 = resource_calendar.create(
{"name": "Test calendar 1", "attendance_ids": []}
)
cls.calendar2 = resource_calendar.create(
{"name": "Test calendar 2", "attendance_ids": []}
)
for day in range(5): # From monday to friday
cls.calendar1.attendance_ids = [
(
0,
0,
{
"name": "Attendance",
"dayofweek": str(day),
"hour_from": "08",
"hour_to": "12",
},
),
(
0,
0,
{
"name": "Attendance",
"dayofweek": str(day),
"hour_from": "13",
"hour_to": "17",
},
),
]
cls.calendar2.attendance_ids = [
(
0,
0,
{
"name": "Attendance",
"dayofweek": str(day),
"hour_from": "07",
"hour_to": "14",
},
),
]
cls.employee = cls.env["hr.employee"].create({"name": "Test employee"})
cls.leave1 = cls.env["resource.calendar.leaves"].create(
{
"name": "Test leave",
"calendar_id": cls.calendar1.id,
"resource_id": cls.employee.resource_id.id,
"date_from": "2019-06-01",
"date_to": "2019-06-10",
}
)
cls.global_leave1 = cls.env["resource.calendar.leaves"].create(
{
"name": "Global Leave 1",
"date_from": "2019-03-01",
"date_to": "2019-03-02",
}
)
cls.global_leave2 = cls.env["resource.calendar.leaves"].create(
{
"name": "Global Leave 2",
"date_from": "2020-03-12",
"date_to": "2020-03-13",
}
)
cls.global_leave3 = cls.env["resource.calendar.leaves"].create(
{
"name": "Global Leave 3",
"date_from": "2020-03-09",
"date_to": "2020-03-10",
}
)
cls.calendar1.global_leave_ids = [
(6, 0, [cls.global_leave1.id, cls.global_leave2.id])
]
cls.calendar2.global_leave_ids = [(6, 0, [cls.global_leave3.id])]
# By default a calendar_ids is set, we remove it to better clarify the tests.
cls.employee.write({"calendar_ids": [(2, cls.employee.calendar_ids.id)]})
def test_calendar_planning(self):
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id}),
(0, 0, {"date_start": "2020-01-01", "calendar_id": self.calendar2.id}),
]
self.assertTrue(self.employee.resource_calendar_id)
calendar = self.employee.resource_calendar_id
self.assertEqual(len(calendar.attendance_ids), 15)
self.assertEqual(
len(
calendar.attendance_ids.filtered(
lambda x: x.date_from == fields.Date.to_date("2020-01-01")
)
),
5,
)
self.assertEqual(
len(
calendar.attendance_ids.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-31")
)
),
10,
)
# Change one line
calendar_line = self.employee.calendar_ids.filtered(
lambda x: x.date_end == fields.Date.to_date("2019-12-31")
)
calendar_line.date_end = "2019-12-30"
calendar = self.employee.resource_calendar_id
self.assertEqual(
len(
calendar.attendance_ids.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-30")
)
),
10,
)
calendar_line.unlink()
self.assertEqual(
len(
calendar.attendance_ids.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-30")
)
),
0,
)
self.assertEqual(len(calendar.attendance_ids), 5)
self.calendar2.write(
{
"attendance_ids": [
(
0,
0,
{
"name": "Attendance",
"dayofweek": "6",
"hour_from": "08",
"hour_to": "12",
},
)
],
}
)
self.assertEqual(len(calendar.attendance_ids), 6)
# 2 week calendars
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id})
]
self.calendar1.switch_calendar_type()
self.assertTrue(self.employee.resource_calendar_id.two_weeks_calendar)
# Calendar 1 has 20 lines + Calendar 2 has 6 lines that are duplicated
# in the odd and even week + even week label + odd week label
self.assertEqual(
len(self.employee.resource_calendar_id.attendance_ids), 20 + 6 * 2 + 2
)
def test_calendar_planning_two_weeks(self):
self.calendar1.switch_calendar_type()
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id}),
(0, 0, {"date_start": "2020-01-01", "calendar_id": self.calendar2.id}),
]
self.assertEqual(
len(self.employee.resource_calendar_id.attendance_ids), 20 + 5 * 2 + 2
)
items = self.employee.resource_calendar_id.attendance_ids
items_with_sections = items.filtered(lambda x: x.display_type)
self.assertEqual(len(items_with_sections), 2)
items_date_to = items.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-31")
)
self.assertEqual(len(items_date_to), 20)
self.assertEqual(len(items_date_to.filtered(lambda x: x.week_type == "0")), 10)
self.assertEqual(len(items_date_to.filtered(lambda x: x.week_type == "1")), 10)
items_date_from = items.filtered(
lambda x: x.date_from == fields.Date.to_date("2020-01-01")
)
self.assertEqual(len(items_date_from), 10)
self.assertEqual(len(items_date_from.filtered(lambda x: x.week_type == "0")), 5)
self.assertEqual(len(items_date_from.filtered(lambda x: x.week_type == "1")), 5)
items_without_sections = items - items_with_sections
self.assertEqual(
len(items_without_sections.filtered(lambda x: x.week_type == "0")), 10 + 5
)
self.assertEqual(
len(items_without_sections.filtered(lambda x: x.week_type == "1")), 10 + 5
)
self.calendar2.switch_calendar_type()
items = self.employee.resource_calendar_id.attendance_ids
items_with_sections = items.filtered(lambda x: x.display_type)
items_without_sections = items - items_with_sections
self.assertEqual(len(items), 20 + 20 + 2)
self.assertEqual(len(items_with_sections), 2)
items_date_to = items.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-31")
)
self.assertEqual(len(items_date_to), 20)
items_date_from = items.filtered(
lambda x: x.date_from == fields.Date.to_date("2020-01-01")
)
self.assertEqual(len(items_date_from), 20)
items_week_0 = items_without_sections.filtered(lambda x: x.week_type == "0")
self.assertEqual(len(items_week_0), 10 + 10)
self.assertEqual(
len(
items_week_0.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-31")
)
),
5 + 5,
)
self.assertEqual(
len(
items_week_0.filtered(
lambda x: x.date_from == fields.Date.to_date("2020-01-01")
)
),
5 + 5,
)
items_week_1 = items_without_sections.filtered(lambda x: x.week_type == "1")
self.assertEqual(len(items_week_1), 10 + 10)
self.assertEqual(
len(
items_week_1.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-31")
)
),
5 + 5,
)
self.assertEqual(
len(
items_week_1.filtered(
lambda x: x.date_from == fields.Date.to_date("2020-01-01")
)
),
5 + 5,
)
def test_calendar_planning_two_weeks_multi(self):
self.calendar1.switch_calendar_type()
self.calendar2.switch_calendar_type()
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id}),
(
0,
0,
{
"date_start": "2020-01-01",
"date_end": "2020-01-31",
"calendar_id": self.calendar2.id,
},
),
(
0,
0,
{
"date_start": "2020-02-01",
"date_end": "2020-02-02",
"calendar_id": self.calendar1.id,
},
),
(0, 0, {"date_start": "2020-01-03", "calendar_id": self.calendar2.id}),
]
items = self.employee.resource_calendar_id.attendance_ids
items_with_sections = items.filtered(lambda x: x.display_type)
items_without_sections = items - items_with_sections
self.assertEqual(len(items), (20 * 2) + (20 * 2) + 2)
self.assertEqual(len(items_with_sections), 2)
items_week_0 = items_without_sections.filtered(lambda x: x.week_type == "0")
self.assertEqual(
len(
items_week_0.filtered(
lambda x: x.date_to == fields.Date.to_date("2019-12-31")
)
),
10,
)
self.assertEqual(
len(
items_week_0.filtered(
lambda x: x.date_to == fields.Date.to_date("2020-01-31")
)
),
10,
)
self.assertEqual(
len(
items_week_0.filtered(
lambda x: x.date_to == fields.Date.to_date("2020-02-02")
)
),
10,
)
self.assertEqual(
len(
items_week_0.filtered(
lambda x: x.date_from == fields.Date.to_date("2020-01-03")
)
),
10,
)
self.assertEqual(len(items_week_0), 20 + 20)
items_week_1 = items_without_sections.filtered(lambda x: x.week_type == "1")
self.assertEqual(len(items_week_0), len(items_week_1))
def test_post_install_hook(self):
self.employee.resource_calendar_id = self.calendar1.id
post_init_hook(self.env.cr, self.env.registry, self.employee)
self.assertNotEqual(self.employee.resource_calendar_id, self.calendar1)
# Check that no change is done on original calendar
self.assertEqual(len(self.calendar1.attendance_ids), 10)
self.assertEqual(len(self.employee.calendar_ids), 1)
self.assertFalse(self.employee.calendar_ids.date_start)
self.assertFalse(self.employee.calendar_ids.date_end)
# Check that the employee leaves are transferred to the new calendar
# And that global leaves remain untouched
self.assertEqual(
self.calendar1.leave_ids, self.global_leave1 + self.global_leave2
)
self.assertTrue(
self.leave1.id in self.employee.resource_calendar_id.leave_ids.ids
)
# Test that global leaves are copied to the autogenerated calendar on post install hook
self.assertEqual(
{
global_leave.name
for global_leave in self.employee.resource_calendar_id.global_leave_ids
},
{"Global Leave 1", "Global Leave 2"},
)
def test_post_install_hook_several_calendaries(self):
self.calendar1.attendance_ids[0].date_from = "2019-01-01"
self.calendar1.attendance_ids[1].date_from = "2019-01-01"
self.employee.resource_calendar_id = self.calendar1.id
post_init_hook(self.env.cr, self.env.registry, self.employee)
self.assertNotEqual(self.employee.resource_calendar_id, self.calendar1)
# Check that no change is done on original calendar
self.assertEqual(len(self.calendar1.attendance_ids), 10)
self.assertEqual(len(self.employee.calendar_ids), 2)
self.assertEqual(
len(self.employee.calendar_ids[0].calendar_id.attendance_ids),
2,
)
self.assertEqual(
len(self.employee.calendar_ids[1].calendar_id.attendance_ids),
8,
)
def test_resource_calendar_constraint(self):
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id})
]
with self.assertRaises(exceptions.ValidationError):
self.calendar1.write({"active": False})
self.employee.write({"calendar_ids": [(2, self.employee.calendar_ids.id)]})
self.calendar1.write({"active": False})
self.assertFalse(self.calendar1.active)
def test_resource_calendar_constraint_company_id(self):
main_company = self.env.ref("base.main_company")
self.calendar1.company_id = main_company
self.employee.company_id = main_company
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id})
]
company2 = self.env["res.company"].create({"name": "Test company"})
with self.assertRaises(exceptions.ValidationError):
self.calendar1.company_id = company2
def test_employee_with_calendar_ids(self):
employee = self.env["hr.employee"].create(
{
"name": "Test employee",
"calendar_ids": [
(
0,
0,
{"date_start": "2020-01-01", "calendar_id": self.calendar2.id},
),
],
}
)
self.assertTrue(employee.resource_calendar_id.auto_generate)
def test_copy_global_leaves(self):
# test that global leaves are combined from calendar_ids
global_leave_ids_cal1 = self.calendar1.global_leave_ids.ids
self.employee.calendar_ids = [
(0, 0, {"date_end": "2020-03-03", "calendar_id": self.calendar1.id}),
(0, 0, {"date_start": "2020-03-03", "calendar_id": self.calendar2.id}),
]
self.assertEqual(
{
global_leave.name
for global_leave in self.employee.resource_calendar_id.global_leave_ids
},
{"Global Leave 1", "Global Leave 3"},
)
# test that global leaves on original calendar are not changed
self.assertEqual(global_leave_ids_cal1, self.calendar1.global_leave_ids.ids)
def test_employee_copy(self):
self.employee.calendar_ids = [
(0, 0, {"date_end": "2019-12-31", "calendar_id": self.calendar1.id}),
(0, 0, {"date_start": "2020-01-01", "calendar_id": self.calendar2.id}),
]
self.assertTrue(self.employee.resource_calendar_id)
self.assertTrue(self.employee.resource_calendar_id.auto_generate)
employee2 = self.employee.copy()
self.assertIn(self.calendar1, employee2.mapped("calendar_ids.calendar_id"))
self.assertIn(self.calendar2, employee2.mapped("calendar_ids.calendar_id"))
self.assertTrue(employee2.resource_calendar_id)
self.assertTrue(employee2.resource_calendar_id.auto_generate)
self.assertNotEqual(
self.employee.resource_calendar_id, employee2.resource_calendar_id
)
def test_user_action_create_employee(self):
user = new_test_user(self.env, login="test-user")
user.action_create_employee()
self.assertIn(
user.company_id.resource_calendar_id,
user.employee_id.mapped("calendar_ids.calendar_id"),
)
def test_create_employee_multi(self):
employees = self.env["hr.employee"].create(
[
{"name": "multi employee 1"},
{"name": "multi employee 2"},
]
)
self.assertEqual(len(employees), 2)

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_employee_form" model="ir.ui.view">
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form" />
<!-- It is necessary to set a high priority to avoid that if hr_contract
is installed later, the calendar is still hidden. !-->
<field name="priority">99</field>
<field name="arch" type="xml">
<field name="resource_calendar_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
<field name="resource_calendar_id" position="after">
<sheet colspan="2">
<field name="calendar_ids" nolabel="1">
<tree editable="top">
<field name="company_id" invisible="1" />
<field name="date_start" />
<field name="date_end" />
<field
name="calendar_id"
context="{'default_company_id': company_id}"
/>
</tree>
</field>
</sheet>
</field>
</field>
</record>
<record id="hr_employee_public_view_form" model="ir.ui.view">
<field name="name">hr.employee.public.form</field>
<field name="model">hr.employee.public</field>
<field name="inherit_id" ref="hr.hr_employee_public_view_form" />
<field name="arch" type="xml">
<field name="resource_calendar_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
</odoo>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2023 Creu Blanca
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="resource_calendar_form" model="ir.ui.view">
<field name="model">resource.calendar</field>
<field name="inherit_id" ref="resource.resource_calendar_form" />
<field name="arch" type="xml">
<notebook position="inside">
<page name="employee_calendar" string="Employee Calendars">
<field name="employee_calendar_ids">
<tree editable="top" create="0">
<field name="company_id" invisible="1" />
<field name="date_start" />
<field name="date_end" />
<field name="employee_id" />
</tree>
</field>
</page>
</notebook>
</field>
</record>
</odoo>

View file

@ -0,0 +1,42 @@
[project]
name = "odoo-bringout-oca-hr-hr_employee_calendar_planning"
version = "16.0.0"
description = "Employee Calendar Planning - Odoo addon"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-hr>=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 = ["hr_employee_calendar_planning"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]