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,46 @@
# Base Time Window
Odoo addon: base_time_window
## Installation
```bash
pip install odoo-bringout-oca-server-tools-base_time_window
```
## Dependencies
This addon depends on:
- base
## Manifest Information
- **Name**: Base Time Window
- **Version**: 16.0.1.1.0
- **Category**: Technical Settings
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/server-tools](https://github.com/OCA/server-tools) branch 16.0, addon `base_time_window`.
## 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
- Reports: doc/REPORTS.md
- Security: doc/SECURITY.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,139 @@
================
Base Time Window
================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:d4a4d2b2f23208766c536ae69f930541425fc8a73ff49819bd69c94ccf3b252a
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github
:target: https://github.com/OCA/server-tools/tree/16.0/base_time_window
:alt: OCA/server-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-base_time_window
: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/server-tools&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module provides base classes and models to manage time windows through
`time.window.mixin`.
**Table of contents**
.. contents::
:local:
Usage
=====
Example implementation for the mixin can be found in module `test_base_time_window`.
As a time window will always be linked to a related model thourgh a M2o relation,
when defining the new model inheriting the mixin, one should pay attention to the
following points in order to have the overlapping check work properly:
- Define class property `_overlap_check_field`: This must state the M2o field to
use for the to check of overlapping time window records linked to a specific
record of the related model.
- Add the M2o field to the related model in the `api.constrains`:
For example:
.. code-block:: python
class PartnerTimeWindow(models.Model):
_name = 'partner.time.window'
_inherit = 'time.window.mixin'
partner_id = fields.Many2one(
res.partner', required=True, index=True, ondelete='cascade'
)
_overlap_check_field = 'partner_id'
@api.constrains('partner_id')
def check_window_no_overlaps(self):
return super().check_window_no_overlaps()
Known issues / Roadmap
======================
* Storing times using `float_time` widget requires extra processing to ensure
computations are done in the right timezone, because the value is not stored
as UTC in the database, and must therefore be related to a `tz` field.
`float_time` in this sense should only be used for durations and not for a
"point in time" as this is always needs a Date for a timezone conversion to
be done properly. (Because a conversion from UTC to e.g. Europe/Brussels won't
give the same result in winter or summer because of Daylight Saving Time).
Therefore the right move would be to use a `resource.calendar` to define time
windows using Datetime with recurrences.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/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/server-tools/issues/new?body=module:%20base_time_window%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
~~~~~~~
* ACSONE SA/NV
* Camptocamp
Contributors
~~~~~~~~~~~~
* Laurent Mignon <laurent.mignon@acsone.eu>
* Akim Juillerat <akim.juillerat@camptocamp.com>
Trobz
* Dung Tran <dungtd@trobz.com>
Other credits
~~~~~~~~~~~~~
The development of this module has been financially supported by:
* Camptocamp
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/16.0/base_time_window>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

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

View file

@ -0,0 +1,14 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
{
"name": "Base Time Window",
"summary": "Base model to handle time windows",
"version": "16.0.1.1.0",
"category": "Technical Settings",
"author": "ACSONE SA/NV, Camptocamp, Odoo Community Association (OCA)",
"license": "AGPL-3",
"website": "https://github.com/OCA/server-tools",
"depends": ["base"],
"data": ["data/time_weekday.xml", "security/ir.model.access.xml"],
"installable": True,
}

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo noupdate="1">
<record model="time.weekday" id="time_weekday_monday">
<field name="name">0</field>
</record>
<record model="time.weekday" id="time_weekday_tuesday">
<field name="name">1</field>
</record>
<record model="time.weekday" id="time_weekday_wednesday">
<field name="name">2</field>
</record>
<record model="time.weekday" id="time_weekday_thursday">
<field name="name">3</field>
</record>
<record model="time.weekday" id="time_weekday_friday">
<field name="name">4</field>
</record>
<record model="time.weekday" id="time_weekday_saturday">
<field name="name">5</field>
</record>
<record model="time.weekday" id="time_weekday_sunday">
<field name="name">6</field>
</record>
</odoo>

View file

@ -0,0 +1,163 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_time_window
#
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: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(end_time)s must be > %(start_time)s"
msgstr ""
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(record_name)s overlaps %(other_name)s"
msgstr ""
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "At least one time.weekday is required"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_uid
msgid "Created by"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_date
msgid "Created on"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__display_name
msgid "Display Name"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__4
msgid "Friday"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_start
msgid "From"
msgstr ""
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "Hour should be between 00 and 23"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__id
msgid "ID"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday____last_update
msgid "Last Modified on"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_uid
msgid "Last Updated by"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_date
msgid "Last Updated on"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__0
msgid "Monday"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__name
msgid "Name"
msgstr ""
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_weekday.py:0
#: model:ir.model.constraint,message:base_time_window.constraint_time_weekday_name_uniq
#, python-format
msgid "Name must be unique"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__5
msgid "Saturday"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__smart_search
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__smart_search
msgid "Smart Search"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__6
msgid "Sunday"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__3
msgid "Thursday"
msgstr ""
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_weekday
msgid "Time Week Day"
msgstr ""
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_window_mixin
msgid "Time Window"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_weekday_ids
msgid "Time Window Weekday"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_end
msgid "To"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__1
msgid "Tuesday"
msgstr ""
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__2
msgid "Wednesday"
msgstr ""
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "{days}: From {start} to {end}"
msgstr ""

View file

@ -0,0 +1,163 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_time_window
#
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: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(end_time)s must be > %(start_time)s"
msgstr "%(end_time)s mora biti > %(start_time)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(record_name)s overlaps %(other_name)s"
msgstr "%(record_name)s se preklapa sa %(other_name)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "At least one time.weekday is required"
msgstr "Potreban je najmanje jedan time.weekday"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__4
msgid "Friday"
msgstr "Petak"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_start
msgid "From"
msgstr "Od"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "Hour should be between 00 and 23"
msgstr "Sat treba biti između 00 i 23"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__id
msgid "ID"
msgstr "ID"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday____last_update
msgid "Last Modified on"
msgstr "Zadnje mijenjano"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_uid
msgid "Last Updated by"
msgstr "Zadnji ažurirao"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__0
msgid "Monday"
msgstr "Ponedjeljak"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__name
msgid "Name"
msgstr "Naziv:"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_weekday.py:0
#: model:ir.model.constraint,message:base_time_window.constraint_time_weekday_name_uniq
#, python-format
msgid "Name must be unique"
msgstr "Naziv mora biti jedinstven"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__5
msgid "Saturday"
msgstr "Subota"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__smart_search
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__smart_search
msgid "Smart Search"
msgstr "Pametna pretraga"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__6
msgid "Sunday"
msgstr "Nedjelja"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__3
msgid "Thursday"
msgstr "Četvrtak"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_weekday
msgid "Time Week Day"
msgstr "Radni dan u sedmici"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_window_mixin
msgid "Time Window"
msgstr "Vremenski okvir"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_weekday_ids
msgid "Time Window Weekday"
msgstr "Dan u sedmici vremenskog okvira"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_end
msgid "To"
msgstr "Za"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__1
msgid "Tuesday"
msgstr "Utorak"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__2
msgid "Wednesday"
msgstr "Srijeda"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "{days}: From {start} to {end}"
msgstr "{days}: Od {start} do {end}"

View file

@ -0,0 +1,166 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_time_window
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-11-11 15:39+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: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(end_time)s must be > %(start_time)s"
msgstr "%(end_time)s debe ser > %(start_time)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(record_name)s overlaps %(other_name)s"
msgstr "%(record_name)s se solapa con %(other_name)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "At least one time.weekday is required"
msgstr "Al menos se requiere una vez por semana"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_date
msgid "Created on"
msgstr "Creado el"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__4
msgid "Friday"
msgstr "Viernes"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_start
msgid "From"
msgstr "Desde"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "Hour should be between 00 and 23"
msgstr "La hora debe estar comprendida entre 00 y 23"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__id
msgid "ID"
msgstr "ID (identificación)"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday____last_update
msgid "Last Modified on"
msgstr "Última Modifiación el"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_uid
msgid "Last Updated by"
msgstr "Actualizado por Última vez por"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_date
msgid "Last Updated on"
msgstr "Última Actualización el"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__0
msgid "Monday"
msgstr "Lunes"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__name
msgid "Name"
msgstr "Nombre"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_weekday.py:0
#: model:ir.model.constraint,message:base_time_window.constraint_time_weekday_name_uniq
#, python-format
msgid "Name must be unique"
msgstr "El nombre debe ser único"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__5
msgid "Saturday"
msgstr "Sábado"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__smart_search
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__smart_search
msgid "Smart Search"
msgstr "Búsqueda Inteligente"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__6
msgid "Sunday"
msgstr "Domingo"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__3
msgid "Thursday"
msgstr "Jueves"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_weekday
msgid "Time Week Day"
msgstr "Tiempo Semana Día"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_window_mixin
msgid "Time Window"
msgstr "Ventana de Tiempo"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_weekday_ids
msgid "Time Window Weekday"
msgstr "Ventana horaria Día de la semana"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_end
msgid "To"
msgstr "A"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__1
msgid "Tuesday"
msgstr "Martes"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__2
msgid "Wednesday"
msgstr "Miércoles"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "{days}: From {start} to {end}"
msgstr "{days}: De [start] a [end]"

View file

@ -0,0 +1,166 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_time_window
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-06-09 16:09+0000\n"
"Last-Translator: Ignacio Buioli <ibuioli@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.17\n"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(end_time)s must be > %(start_time)s"
msgstr "%(end_time)s debe ser > %(start_time)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(record_name)s overlaps %(other_name)s"
msgstr "%(record_name)s se superpone %(other_name)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "At least one time.weekday is required"
msgstr "Se requiere al menos una vez al día de la semana"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_date
msgid "Created on"
msgstr "Creado en"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__4
msgid "Friday"
msgstr "Viernes"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_start
msgid "From"
msgstr "Desde"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "Hour should be between 00 and 23"
msgstr "Las horas deben ser entre 00 y 23"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__id
msgid "ID"
msgstr "ID"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday____last_update
msgid "Last Modified on"
msgstr "Última modificación en"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_uid
msgid "Last Updated by"
msgstr "Última actualización realizada por"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_date
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__0
msgid "Monday"
msgstr "Lunes"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__name
msgid "Name"
msgstr "Nombre"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_weekday.py:0
#: model:ir.model.constraint,message:base_time_window.constraint_time_weekday_name_uniq
#, python-format
msgid "Name must be unique"
msgstr "El nombre debe ser único"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__5
msgid "Saturday"
msgstr "Sábado"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__smart_search
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__smart_search
msgid "Smart Search"
msgstr "Búsqueda Inteligente"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__6
msgid "Sunday"
msgstr "Domingo"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__3
msgid "Thursday"
msgstr "Jueves"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_weekday
msgid "Time Week Day"
msgstr "Hora Semana Día"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_window_mixin
msgid "Time Window"
msgstr "Ventana de Tiempo"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_weekday_ids
msgid "Time Window Weekday"
msgstr "Ventana de Tiempo Día de la semana"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_end
msgid "To"
msgstr "Hasta"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__1
msgid "Tuesday"
msgstr "Martes"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__2
msgid "Wednesday"
msgstr "Miércoles"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "{days}: From {start} to {end}"
msgstr "{days}: Desde {start} hasta {end}"

View file

@ -0,0 +1,166 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * base_time_window
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-01-08 17:35+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: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(end_time)s must be > %(start_time)s"
msgstr "%(end_time)s deve essere > %(start_time)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "%(record_name)s overlaps %(other_name)s"
msgstr "%(record_name)s si sovrappone a %(other_name)s"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "At least one time.weekday is required"
msgstr "È richiesto almeno un time.weekday"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_uid
msgid "Created by"
msgstr "Creato da"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__create_date
msgid "Created on"
msgstr "Creato il"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__display_name
msgid "Display Name"
msgstr "Nome visualizzato"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__4
msgid "Friday"
msgstr "Venerdì"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_start
msgid "From"
msgstr "Dal"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "Hour should be between 00 and 23"
msgstr "L'ora deve essere tra 00 e 23"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__id
msgid "ID"
msgstr "ID"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday____last_update
msgid "Last Modified on"
msgstr "Ultima modifica il"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_uid
msgid "Last Updated by"
msgstr "Ultimo aggiornamento di"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__write_date
msgid "Last Updated on"
msgstr "Ultimo aggiornamento il"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__0
msgid "Monday"
msgstr "Lunedì"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__name
msgid "Name"
msgstr "Nome"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_weekday.py:0
#: model:ir.model.constraint,message:base_time_window.constraint_time_weekday_name_uniq
#, python-format
msgid "Name must be unique"
msgstr "Il nome deve essere univoco"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__5
msgid "Saturday"
msgstr "Sabato"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_weekday__smart_search
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__smart_search
msgid "Smart Search"
msgstr "Ricerca intelligente"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__6
msgid "Sunday"
msgstr "Domenica"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__3
msgid "Thursday"
msgstr "Giovedì"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_weekday
msgid "Time Week Day"
msgstr "Ora giorno della settimana"
#. module: base_time_window
#: model:ir.model,name:base_time_window.model_time_window_mixin
msgid "Time Window"
msgstr "Intervallo orario"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_weekday_ids
msgid "Time Window Weekday"
msgstr "Intervallo orario giorno della settimana"
#. module: base_time_window
#: model:ir.model.fields,field_description:base_time_window.field_time_window_mixin__time_window_end
msgid "To"
msgstr "Al"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__1
msgid "Tuesday"
msgstr "Martedì"
#. module: base_time_window
#: model:ir.model.fields.selection,name:base_time_window.selection__time_weekday__name__2
msgid "Wednesday"
msgstr "Mercoledì"
#. module: base_time_window
#. odoo-python
#: code:addons/base_time_window/models/time_window_mixin.py:0
#, python-format
msgid "{days}: From {start} to {end}"
msgstr "{days}: dal {start} al {end}"

View file

@ -0,0 +1,2 @@
from . import time_weekday
from . import time_window_mixin

View file

@ -0,0 +1,89 @@
# Copyright 2020 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models, tools
class TimeWeekday(models.Model):
_name = "time.weekday"
_description = "Time Week Day"
name = fields.Selection(
selection=[
("0", "Monday"),
("1", "Tuesday"),
("2", "Wednesday"),
("3", "Thursday"),
("4", "Friday"),
("5", "Saturday"),
("6", "Sunday"),
],
required=True,
)
_sql_constraints = [("name_uniq", "UNIQUE(name)", _("Name must be unique"))]
@api.depends("name")
def _compute_display_name(self):
"""
WORKAROUND since Odoo doesn't handle properly records where name is
a selection
"""
translated_values = dict(self._fields["name"]._description_selection(self.env))
for record in self:
record.display_name = translated_values[record.name]
def name_get(self):
"""
WORKAROUND since Odoo doesn't handle properly records where name is
a selection
"""
return [(r.id, r.display_name) for r in self]
@api.model
@tools.ormcache("name")
def _get_id_by_name(self, name):
return self.search([("name", "=", name)], limit=1).id
@api.model_create_multi
def create(self, vals_list):
records = super().create(vals_list)
self._get_id_by_name.clear_cache(self)
return records
def write(self, vals):
result = super().write(vals)
self._get_id_by_name.clear_cache(self)
return result
def unlink(self):
result = super().unlink()
self._get_id_by_name.clear_cache(self)
return result
def _get_next_weekday_date(self, date_from=False, include_date_from=True):
"""Returns the next Date matching weekday
:param date_from: Date object from which we start searching for next weekday
:param include_date_from: Allows to return date from if it's same weekday
:return Date object matching the weekday
"""
self.ensure_one()
if not date_from:
date_from = fields.Date.today()
next_weekday_delta = int(self.name) - date_from.weekday()
if next_weekday_delta < 0:
next_weekday_delta += 7
elif next_weekday_delta == 0 and not include_date_from:
next_weekday_delta += 7
return fields.Date.add(date_from, days=next_weekday_delta)
def _get_next_weekdays_date(self, date_from=False, include_date_from=True):
return min(
[
weekday._get_next_weekday_date(
date_from=date_from, include_date_from=include_date_from
)
for weekday in self
]
)

View file

@ -0,0 +1,137 @@
# Copyright 2020 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import math
from datetime import time
from psycopg2.extensions import AsIs
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.misc import format_time
class TimeWindowMixin(models.AbstractModel):
_name = "time.window.mixin"
_description = "Time Window"
_order = "time_window_start"
# TODO patch api.constrains with field here?
_time_window_overlap_check_field = False
time_window_start = fields.Float("From", required=True)
time_window_end = fields.Float("To", required=True)
time_window_weekday_ids = fields.Many2many(
comodel_name="time.weekday", required=True
)
@api.constrains("time_window_start", "time_window_end", "time_window_weekday_ids")
def check_window_no_overlaps(self):
weekdays_field = self._fields["time_window_weekday_ids"]
for record in self:
if record.time_window_start > record.time_window_end:
raise ValidationError(
_("%(end_time)s must be > %(start_time)s")
% (
{
"end_time": self.float_to_time_repr(record.time_window_end),
"start_time": self.float_to_time_repr(
record.time_window_start
),
}
)
)
if not record.time_window_weekday_ids:
raise ValidationError(_("At least one time.weekday is required"))
# here we use a plain SQL query to benefit of the numrange
# function available in PostgresSQL
# (http://www.postgresql.org/docs/current/static/rangetypes.html)
SQL = """
SELECT
id
FROM
%(table)s w
join %(relation)s as d
on d.%(relation_window_fkey)s = w.id
WHERE
NUMRANGE(w.time_window_start::numeric,
w.time_window_end::numeric) &&
NUMRANGE(%(start)s::numeric, %(end)s::numeric)
AND w.id != %(window_id)s
AND d.%(relation_week_day_fkey)s in %(weekday_ids)s
AND w.%(check_field)s = %(check_field_id)s;"""
self.env.cr.execute(
SQL,
dict(
table=AsIs(self._table),
relation=AsIs(weekdays_field.relation),
relation_window_fkey=AsIs(weekdays_field.column1),
relation_week_day_fkey=AsIs(weekdays_field.column2),
start=record.time_window_start,
end=record.time_window_end,
window_id=record.id,
weekday_ids=tuple(record.time_window_weekday_ids.ids),
check_field=AsIs(self._time_window_overlap_check_field),
check_field_id=record[self._time_window_overlap_check_field].id,
),
)
res = self.env.cr.fetchall()
if res:
other = self.browse(res[0][0])
raise ValidationError(
_("%(record_name)s overlaps %(other_name)s")
% (
{
"record_name": record.display_name,
"other_name": other.display_name,
}
)
)
@api.depends("time_window_start", "time_window_end", "time_window_weekday_ids")
def _compute_display_name(self):
for record in self:
record.display_name = _("{days}: From {start} to {end}").format(
days=", ".join(record.time_window_weekday_ids.mapped("display_name")),
start=format_time(self.env, record.get_time_window_start_time()),
end=format_time(self.env, record.get_time_window_end_time()),
)
@api.constrains("time_window_start", "time_window_end")
def _check_window_under_twenty_four_hours(self):
error_msg = _("Hour should be between 00 and 23")
for record in self:
if record.time_window_start:
hour, minute = self._get_hour_min_from_value(record.time_window_start)
if hour > 23:
raise ValidationError(error_msg)
if record.time_window_end:
hour, minute = self._get_hour_min_from_value(record.time_window_end)
if hour > 23:
raise ValidationError(error_msg)
@api.model
def _get_hour_min_from_value(self, value):
hour = math.floor(value)
minute = round((value % 1) * 60)
if minute == 60:
minute = 0
hour += 1
return hour, minute
@api.model
def float_to_time_repr(self, value):
pattern = "%02d:%02d"
hour, minute = self._get_hour_min_from_value(value)
return pattern % (hour, minute)
@api.model
def float_to_time(self, value):
hour, minute = self._get_hour_min_from_value(value)
return time(hour=hour, minute=minute)
def get_time_window_start_time(self):
return self.float_to_time(self.time_window_start)
def get_time_window_end_time(self):
return self.float_to_time(self.time_window_end)

View file

@ -0,0 +1,6 @@
* Laurent Mignon <laurent.mignon@acsone.eu>
* Akim Juillerat <akim.juillerat@camptocamp.com>
Trobz
* Dung Tran <dungtd@trobz.com>

View file

@ -0,0 +1,3 @@
The development of this module has been financially supported by:
* Camptocamp

View file

@ -0,0 +1,2 @@
This module provides base classes and models to manage time windows through
`time.window.mixin`.

View file

@ -0,0 +1,11 @@
* Storing times using `float_time` widget requires extra processing to ensure
computations are done in the right timezone, because the value is not stored
as UTC in the database, and must therefore be related to a `tz` field.
`float_time` in this sense should only be used for durations and not for a
"point in time" as this is always needs a Date for a timezone conversion to
be done properly. (Because a conversion from UTC to e.g. Europe/Brussels won't
give the same result in winter or summer because of Daylight Saving Time).
Therefore the right move would be to use a `resource.calendar` to define time
windows using Datetime with recurrences.

View file

@ -0,0 +1,30 @@
Example implementation for the mixin can be found in module `test_base_time_window`.
As a time window will always be linked to a related model thourgh a M2o relation,
when defining the new model inheriting the mixin, one should pay attention to the
following points in order to have the overlapping check work properly:
- Define class property `_overlap_check_field`: This must state the M2o field to
use for the to check of overlapping time window records linked to a specific
record of the related model.
- Add the M2o field to the related model in the `api.constrains`:
For example:
.. code-block:: python
class PartnerTimeWindow(models.Model):
_name = 'partner.time.window'
_inherit = 'time.window.mixin'
partner_id = fields.Many2one(
res.partner', required=True, index=True, ondelete='cascade'
)
_overlap_check_field = 'partner_id'
@api.constrains('partner_id')
def check_window_no_overlaps(self):
return super().check_window_no_overlaps()

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.model.access" id="time_weekday_access_read">
<field name="name">time.weekday access read</field>
<field name="model_id" ref="model_time_weekday" />
<field name="group_id" ref="base.group_user" />
<field name="perm_read" eval="1" />
<field name="perm_create" eval="0" />
<field name="perm_write" eval="0" />
<field name="perm_unlink" eval="0" />
</record>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,484 @@
<!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>Base Time Window</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="base-time-window">
<h1 class="title">Base Time Window</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:d4a4d2b2f23208766c536ae69f930541425fc8a73ff49819bd69c94ccf3b252a
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/server-tools/tree/16.0/base_time_window"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-base_time_window"><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/server-tools&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 provides base classes and models to manage time windows through
<cite>time.window.mixin</cite>.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-7">Other credits</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-8">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>Example implementation for the mixin can be found in module <cite>test_base_time_window</cite>.</p>
<p>As a time window will always be linked to a related model thourgh a M2o relation,
when defining the new model inheriting the mixin, one should pay attention to the
following points in order to have the overlapping check work properly:</p>
<ul class="simple">
<li>Define class property <cite>_overlap_check_field</cite>: This must state the M2o field to
use for the to check of overlapping time window records linked to a specific
record of the related model.</li>
<li>Add the M2o field to the related model in the <cite>api.constrains</cite>:</li>
</ul>
<p>For example:</p>
<pre class="code python literal-block">
<span class="k">class</span> <span class="nc">PartnerTimeWindow</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span><span class="w">
</span> <span class="n">_name</span> <span class="o">=</span> <span class="s1">'partner.time.window'</span><span class="w">
</span> <span class="n">_inherit</span> <span class="o">=</span> <span class="s1">'time.window.mixin'</span><span class="w">
</span> <span class="n">partner_id</span> <span class="o">=</span> <span class="n">fields</span><span class="o">.</span><span class="n">Many2one</span><span class="p">(</span><span class="w">
</span> <span class="n">res</span><span class="o">.</span><span class="n">partner</span><span class="s1">', required=True, index=True, ondelete='</span><span class="n">cascade</span><span class="s1">'</span><span class="w">
</span> <span class="p">)</span><span class="w">
</span> <span class="n">_overlap_check_field</span> <span class="o">=</span> <span class="s1">'partner_id'</span><span class="w">
</span> <span class="nd">&#64;api</span><span class="o">.</span><span class="n">constrains</span><span class="p">(</span><span class="s1">'partner_id'</span><span class="p">)</span><span class="w">
</span> <span class="k">def</span> <span class="nf">check_window_no_overlaps</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span><span class="w">
</span> <span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">check_window_no_overlaps</span><span class="p">()</span>
</pre>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
<ul>
<li><p class="first">Storing times using <cite>float_time</cite> widget requires extra processing to ensure
computations are done in the right timezone, because the value is not stored
as UTC in the database, and must therefore be related to a <cite>tz</cite> field.</p>
<p><cite>float_time</cite> in this sense should only be used for durations and not for a
“point in time” as this is always needs a Date for a timezone conversion to
be done properly. (Because a conversion from UTC to e.g. Europe/Brussels wont
give the same result in winter or summer because of Daylight Saving Time).</p>
<p>Therefore the right move would be to use a <cite>resource.calendar</cite> to define time
windows using Datetime with recurrences.</p>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/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/server-tools/issues/new?body=module:%20base_time_window%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>ACSONE SA/NV</li>
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Laurent Mignon &lt;<a class="reference external" href="mailto:laurent.mignon&#64;acsone.eu">laurent.mignon&#64;acsone.eu</a>&gt;</li>
<li>Akim Juillerat &lt;<a class="reference external" href="mailto:akim.juillerat&#64;camptocamp.com">akim.juillerat&#64;camptocamp.com</a>&gt;</li>
</ul>
<p>Trobz</p>
<ul class="simple">
<li>Dung Tran &lt;<a class="reference external" href="mailto:dungtd&#64;trobz.com">dungtd&#64;trobz.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
<h2><a class="toc-backref" href="#toc-entry-7">Other credits</a></h2>
<p>The development of this module has been financially supported by:</p>
<ul class="simple">
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/16.0/base_time_window">OCA/server-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View file

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

View file

@ -0,0 +1,61 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo.fields import Date
from odoo.tests import SavepointCase
class TestWeekday(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
time_weekday_mapping = dict(cls.env["time.weekday"]._fields["name"].selection)
for val, name in time_weekday_mapping.items():
setattr(
cls,
name.lower(),
cls.env["time.weekday"].search([("name", "=", val)], limit=1),
)
def test_next_weekday_date(self):
# 2024-01-01 is Monday, next Monday (including date_from) is 2024-01-01
self.assertEqual(
self.monday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-01"),
)
# 2024-01-01 is Monday, next Monday (excluding date_from) is 2024-01-08
self.assertEqual(
self.monday._get_next_weekday_date(
Date.to_date("2024-01-01"), include_date_from=False
),
Date.to_date("2024-01-08"),
)
# 2024-01-01 is Monday, next Tuesday is 2024-01-02
self.assertEqual(
self.tuesday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-02"),
)
# 2024-01-01 is Monday, next Wednesday is 2024-01-03
self.assertEqual(
self.wednesday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-03"),
)
# 2024-01-01 is Monday, next Thursday is 2024-01-04
self.assertEqual(
self.thursday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-04"),
)
# 2024-01-01 is Monday, next Friday is 2024-01-05
self.assertEqual(
self.friday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-05"),
)
# 2024-01-01 is Monday, next Saturday is 2024-01-06
self.assertEqual(
self.saturday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-06"),
)
# 2024-01-01 is Monday, next Sunday is 2024-01-07
self.assertEqual(
self.sunday._get_next_weekday_date(Date.to_date("2024-01-01")),
Date.to_date("2024-01-07"),
)

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 Base_time_window Module - base_time_window
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 base_time_window. 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:
- base

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

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-server-tools-base_time_window"
# or
uv pip install odoo-bringout-oca-server-tools-base_time_window"
```

View file

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

View file

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

View file

@ -0,0 +1,73 @@
# Security
Access control and security definitions in base_time_window.
## Access Control Lists (ACLs)
Model access permissions defined in:
- **[all_odoo_addons_repos.txt](../all_odoo_addons_repos.txt)**
- 318 model access rules
- **[bosnian_translations.json](../bosnian_translations.json)**
- 50 model access rules
- **[bosnian_translations_output.json](../bosnian_translations_output.json)**
- 444 model access rules
- **[CHANGELOG.md](../CHANGELOG.md)**
- 132 model access rules
- **[delete_all_odoo_addons.sh](../delete_all_odoo_addons.sh)**
- 50 model access rules
- **[delete_odoo_addons.sh](../delete_odoo_addons.sh)**
- 44 model access rules
- **[doc](../doc)**
- **[docker](../docker)**
- **[input](../input)**
- **[nix](../nix)**
- **[odoo.conf](../odoo.conf)**
- 58 model access rules
- **[odoo_packages_bez_l10n.txt](../odoo_packages_bez_l10n.txt)**
- 1947 model access rules
- **[odoo_packages_bringout.txt](../odoo_packages_bringout.txt)**
- 1947 model access rules
- **[odoo_packages.txt](../odoo_packages.txt)**
- 2085 model access rules
- **[output](../output)**
- **[packages](../packages)**
- **[PACKAGES.md](../PACKAGES.md)**
- 298 model access rules
- **[README.md](../README.md)**
- 338 model access rules
- **[scripts](../scripts)**
- **[temp](../temp)**
- **[TRANSLATION_BS_SUMMARY.md](../TRANSLATION_BS_SUMMARY.md)**
- 146 model access rules
- **[verify_deletions.sh](../verify_deletions.sh)**
- 55 model access rules
## Record Rules
Row-level security rules defined in:
## Security Groups & Configuration
Security groups and permissions defined in:
- **[ir.model.access.xml](../base_time_window/security/ir.model.access.xml)**
```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.xml](../base_time_window/security/ir.model.access.xml)**
- Security groups, categories, and XML-based rules
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 base_time_window
```

View file

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

View file

@ -0,0 +1,42 @@
[project]
name = "odoo-bringout-oca-server-tools-base_time_window"
version = "16.0.0"
description = "Base Time Window - Base model to handle time windows"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-base>=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 = ["base_time_window"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]