diff --git a/stock_partner_delivery_window/README.rst b/stock_partner_delivery_window/README.rst new file mode 100644 index 000000000000..afc10420d0bc --- /dev/null +++ b/stock_partner_delivery_window/README.rst @@ -0,0 +1,126 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +============================= +Stock Partner Delivery Window +============================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:65661a2bda79fd6e73bc748f52a0d2338c44dc6cb91c2201ac05350f46cb8b58 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fstock--logistics--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-workflow/tree/19.0/stock_partner_delivery_window + :alt: OCA/stock-logistics-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-workflow-19-0/stock-logistics-workflow-19-0-stock_partner_delivery_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/stock-logistics-workflow&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to define time scheduling preference for delivery +orders on partners, in order to raise a warning when changing a +scheduled date to a time window that is not preferred by this customer. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +On partners form view, under the "Sales & Purchases" tab, one can define +a "Delivery schedule preference" for each partner. + +Possible configurations are: + +- Any time: Do not postpone deliveries +- Fixed time windows: Postpone deliveries to the next preferred time + window +- Weekdays: Postpone deliveries to the next weekday + +After selecting "Fixed time windows", one can define the preferred +delivery windows in the embedded tree view below. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp +* ACSONE SA/NV +* BCIM + +Contributors +------------ + +- Akim Juillerat +- Iván Todorovich +- Matthieu Méquignon +- Jacques-Etienne Baudoux (BCIM) + +Trobz + +- Dung Tran +- Vo Hong Thien + +Other credits +------------- + +The development of this module has been financially supported by: + +- Camptocamp + +The migration of this module from 16.0 to 18.0 was 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. + +.. |maintainer-jbaudoux| image:: https://github.com/jbaudoux.png?size=40px + :target: https://github.com/jbaudoux + :alt: jbaudoux + +Current `maintainer `__: + +|maintainer-jbaudoux| + +This module is part of the `OCA/stock-logistics-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_partner_delivery_window/__init__.py b/stock_partner_delivery_window/__init__.py new file mode 100644 index 000000000000..0650744f6bc6 --- /dev/null +++ b/stock_partner_delivery_window/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_partner_delivery_window/__manifest__.py b/stock_partner_delivery_window/__manifest__.py new file mode 100644 index 000000000000..e27184a575fe --- /dev/null +++ b/stock_partner_delivery_window/__manifest__.py @@ -0,0 +1,24 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +{ + "name": "Stock Partner Delivery Window", + "summary": "Define preferred delivery time windows for partners", + "version": "19.0.1.0.0", + "category": "Inventory", + "author": "Camptocamp, ACSONE SA/NV, BCIM, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/stock-logistics-workflow", + "depends": [ + "base_time_window", + "partner_tz", # shows the tz field on the partner + "stock", + ], + "maintainers": ["jbaudoux"], + "data": [ + "security/ir.model.access.csv", + "views/res_partner.xml", + "views/stock_picking_view.xml", + ], + "demo": ["demo/delivery_time_window.xml"], + "installable": True, +} diff --git a/stock_partner_delivery_window/demo/delivery_time_window.xml b/stock_partner_delivery_window/demo/delivery_time_window.xml new file mode 100644 index 000000000000..f359d9cf58d2 --- /dev/null +++ b/stock_partner_delivery_window/demo/delivery_time_window.xml @@ -0,0 +1,15 @@ + + + + + 10.0 + 18.0 + + + + time_windows + + diff --git a/stock_partner_delivery_window/i18n/es.po b/stock_partner_delivery_window/i18n/es.po new file mode 100644 index 000000000000..de0eadbe7fd2 --- /dev/null +++ b/stock_partner_delivery_window/i18n/es.po @@ -0,0 +1,230 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_partner_delivery_window +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-10-15 20:38+0000\n" +"Last-Translator: Ivorra78 \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: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__anytime +msgid "Any time" +msgstr "En cualquier momento" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_res_partner +msgid "Contact" +msgstr "Contacto" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "" +"Define the scheduling preference for delivery orders:\n" +"\n" +"* Any time: Do not postpone deliveries\n" +"* Fixed time windows: Postpone deliveries to the next preferred time window\n" +"* Weekdays: Postpone deliveries to the next weekday" +msgstr "" +"Defina la preferencia de programación para las órdenes de entrega:\n" +"\n" +"* A cualquier hora: No posponer entregas\n" +"* Ventanas de tiempo fijas: Aplazar las entregas a la siguiente ventana " +"horaria preferida.\n" +"* Días laborables: Aplazar las entregas al siguiente día laborable" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "Delivery time schedule preference" +msgstr "Preferencia de plazo de entrega" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_window_ids +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_window_ids +msgid "Delivery time windows" +msgstr "Plazos de entrega" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__time_windows +msgid "Fixed time windows" +msgstr "Ventanas temporales fijas" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_start +msgid "From" +msgstr "Desde" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_uid +msgid "Last Updated by" +msgstr "Última Actualización Por" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"No %(date_name)s is set on the picking, cannot check if it is in partner's " +"delivery window." +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__partner_id +msgid "Partner" +msgstr "Socio" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_stock_picking__partner_delivery_window_warning +msgid "Partner Delivery Window Warning" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/res_partner.py:0 +msgid "" +"Please define at least one delivery time window or change preference to Any " +"time" +msgstr "" +"Defina al menos una franja horaria de entrega o cambie la preferencia a " +"Cualquier hora" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_partner_delivery_time_window +msgid "Preferred delivery time windows" +msgstr "Plazos de entrega preferidos" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on following time windows:\n" +"%(window)s" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on working days." +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_weekday_ids +msgid "Time Window Weekday" +msgstr "Ventana horaria Día de la semana" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "Timezone" +msgstr "Zona Horaria" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_end +msgid "To" +msgstr "Hasta" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_stock_picking +msgid "Transfer" +msgstr "Transferencia" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__workdays +msgid "Weekdays (Monday to Friday)" +msgstr "Días laborables (de lunes a viernes)" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "" +"When printing documents and exporting/importing data, time values are " +"computed according to this timezone.\n" +"If the timezone is not set, UTC (Coordinated Universal Time) is used.\n" +"Anywhere else, time values are computed according to the time offset of your " +"web client." +msgstr "" +"Al imprimir documentos y exportar/importar datos, los valores de la hora se " +"calculan según esta zona horaria.\n" +"Si la zona horaria no está definida, se utiliza el UTC (Tiempo Universal " +"Coordinado).\n" +"En cualquier otro caso, los valores horarios se calculan de acuerdo con el " +"desfase horario de su cliente web." + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "delivery date" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "scheduled date" +msgstr "" + +#, python-format +#~ msgid "From %(start)s to %(end)s" +#~ msgstr "Desde %(start)s hasta %(end)s" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación el" + +#, python-format +#~ msgid "Scheduled date does not match partner's Delivery window preference." +#~ msgstr "" +#~ "La fecha programada no coincide con la ventana de entrega preferida por " +#~ "el socio." + +#, python-format +#~ msgid "" +#~ "The scheduled date is {date} ({tz}), but the partner is set to prefer " +#~ "deliveries on following time windows:\n" +#~ "{window}" +#~ msgstr "" +#~ "La fecha prevista es {date} ({tz}), pero el socio está configurado para " +#~ "preferir las entregas en las siguientes ventanas horarias:\n" +#~ "{window}" + +#, python-format +#~ msgid "" +#~ "The scheduled date is {date} ({weekday}), but the partner is set to " +#~ "prefer deliveries on working days." +#~ msgstr "" +#~ "La fecha prevista es {date} ({weekday}), pero el contacto está " +#~ "configurado para preferir las entregas en días laborables." diff --git a/stock_partner_delivery_window/i18n/it.po b/stock_partner_delivery_window/i18n/it.po new file mode 100644 index 000000000000..79166264f077 --- /dev/null +++ b/stock_partner_delivery_window/i18n/it.po @@ -0,0 +1,267 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_partner_delivery_window +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-11-03 08:14+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\n" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__anytime +msgid "Any time" +msgstr "A qualsiasi orario" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_res_partner +msgid "Contact" +msgstr "Contatto" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "" +"Define the scheduling preference for delivery orders:\n" +"\n" +"* Any time: Do not postpone deliveries\n" +"* Fixed time windows: Postpone deliveries to the next preferred time window\n" +"* Weekdays: Postpone deliveries to the next weekday" +msgstr "" +"Definisce le preferenze di schedulazione per gli ordini di consegna:\n" +"\n" +"* A qualsiasi orario: non si rinviano le consegne\n" +"* Intervalli orari prefissati: si rinviano le spedizioni al successivo " +"intervallo orario preferito\n" +"* Giorno della settimana: si rinviano le spedizioni al giorno della " +"settimana successivo" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "Delivery time schedule preference" +msgstr "Preferenze schedulazione ora consegna" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_window_ids +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_window_ids +msgid "Delivery time windows" +msgstr "Intervalli orario consegna" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__time_windows +msgid "Fixed time windows" +msgstr "Intervalli orario prefissati" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_start +msgid "From" +msgstr "Da" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__id +msgid "ID" +msgstr "ID" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"No %(date_name)s is set on the picking, cannot check if it is in partner's " +"delivery window." +msgstr "" +"Nel prelievo manca l'impostazione di %(date_name)s, non si può verificare se " +"è nella finestra di consegna del partner." + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__partner_id +msgid "Partner" +msgstr "Partner" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_stock_picking__partner_delivery_window_warning +msgid "Partner Delivery Window Warning" +msgstr "Avviso finestra consegna partner" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/res_partner.py:0 +msgid "" +"Please define at least one delivery time window or change preference to Any " +"time" +msgstr "" +"Definire almeno un intervallo orario di consegna o cambiare le preferenze a " +"\"A qualsiasi orario\"" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_partner_delivery_time_window +msgid "Preferred delivery time windows" +msgstr "Intervalli orario consegna preferiti" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on following time windows:\n" +"%(window)s" +msgstr "" +"La %(date_name)s è %(date)s (%(tz)s), ma il partner preferisce le consegne " +"nella finestra seguente:\n" +"%(window)s" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on working days." +msgstr "" +"Il %(date_name)s è %(date)s (%(tz)s), ma il partner preferisce le consegne " +"nei giorni lavorativi." + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_weekday_ids +msgid "Time Window Weekday" +msgstr "Intervallo orario giorno della settimana" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "Timezone" +msgstr "Fuso orario" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_end +msgid "To" +msgstr "A" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_stock_picking +msgid "Transfer" +msgstr "Trasferimento" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__workdays +msgid "Weekdays (Monday to Friday)" +msgstr "Giorno della settimana (da lunedì a venerdì)" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "" +"When printing documents and exporting/importing data, time values are " +"computed according to this timezone.\n" +"If the timezone is not set, UTC (Coordinated Universal Time) is used.\n" +"Anywhere else, time values are computed according to the time offset of your " +"web client." +msgstr "" +"Quando si stampano i documenti e si esportano/importano dati, gli orari sono " +"calcolati in base a questo fuso orario.\n" +"Se questo non è impostato, viene usato l'UTC (Coordinated Universal Time).\n" +"In qualunque altra parte, l'orario è calcolato in base regolazione dell'ora " +"del client web." + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "delivery date" +msgstr "data consegna" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "scheduled date" +msgstr "data schedulata" + +#~ msgid "" +#~ "The %(date_name)s is %(date)s %(weekday)s, but the partner is set to " +#~ "prefer deliveries on working days." +#~ msgstr "" +#~ "La %(date_name)s è %(date)s %(weekday)s, ma il partner preferisce le " +#~ "consegne nei giorni lavorativi." + +#~ msgid "" +#~ "No scheduled delivery date is set on the picking, cannot check if it is " +#~ "in partner's delivery window." +#~ msgstr "" +#~ "Nessuna data di consegna schedulata è impostata nel prelievo, impossibile " +#~ "controllare se è nella finestra di consegna del partner." + +#~ msgid "" +#~ "The scheduled date is %(date)s %(weekday)s, but the partner is set to " +#~ "prefer deliveries on working days." +#~ msgstr "" +#~ "La data schedulata è %(date)s %(weekday)s, ma il partner preferisce le " +#~ "consegne nei giorni lavorativi." + +#~ msgid "" +#~ "The scheduled date is %(date)s (%(tz)s), but the partner is set to prefer " +#~ "deliveries on following time windows:\n" +#~ "%(window)s" +#~ msgstr "" +#~ "La data schedulata è %(date)s (%(tz)s), ma il partner ha impostato le " +#~ "consegne preferibilmente nei seguenti intervalli orario:\n" +#~ "%(window)s" + +#, python-format +#~ msgid "From %(start)s to %(end)s" +#~ msgstr "Da %(start)s a %(end)s" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#, python-format +#~ msgid "Scheduled date does not match partner's Delivery window preference." +#~ msgstr "" +#~ "La data schedulata non corrisponde alle preferenze intervallo consegna " +#~ "del partner." + +#, python-format +#~ msgid "" +#~ "The scheduled date is {date} ({tz}), but the partner is set to prefer " +#~ "deliveries on following time windows:\n" +#~ "{window}" +#~ msgstr "" +#~ "La data schedulata è {date} ({tz}), ma il partner ha impostato le " +#~ "consegne preferibilmente nei sequenti intervalli orario:\n" +#~ "{window}" + +#, python-format +#~ msgid "" +#~ "The scheduled date is {date} ({weekday}), but the partner is set to " +#~ "prefer deliveries on working days." +#~ msgstr "" +#~ "La data schedulata è {date} ({weekday}), ma il partner preferisce le " +#~ "consegne nei giorni lavorativi." diff --git a/stock_partner_delivery_window/i18n/pt_BR.po b/stock_partner_delivery_window/i18n/pt_BR.po new file mode 100644 index 000000000000..aa40cd136599 --- /dev/null +++ b/stock_partner_delivery_window/i18n/pt_BR.po @@ -0,0 +1,183 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_partner_delivery_window +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: pt_BR\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: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__anytime +msgid "Any time" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_res_partner +msgid "Contact" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_date +msgid "Created on" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "" +"Define the scheduling preference for delivery orders:\n" +"\n" +"* Any time: Do not postpone deliveries\n" +"* Fixed time windows: Postpone deliveries to the next preferred time window\n" +"* Weekdays: Postpone deliveries to the next weekday" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "Delivery time schedule preference" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_window_ids +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_window_ids +msgid "Delivery time windows" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__time_windows +msgid "Fixed time windows" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_start +msgid "From" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__id +msgid "ID" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"No %(date_name)s is set on the picking, cannot check if it is in partner's " +"delivery window." +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__partner_id +msgid "Partner" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_stock_picking__partner_delivery_window_warning +msgid "Partner Delivery Window Warning" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/res_partner.py:0 +msgid "" +"Please define at least one delivery time window or change preference to Any " +"time" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_partner_delivery_time_window +msgid "Preferred delivery time windows" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on following time windows:\n" +"%(window)s" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on working days." +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_weekday_ids +msgid "Time Window Weekday" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "Timezone" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_end +msgid "To" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__workdays +msgid "Weekdays (Monday to Friday)" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "" +"When printing documents and exporting/importing data, time values are " +"computed according to this timezone.\n" +"If the timezone is not set, UTC (Coordinated Universal Time) is used.\n" +"Anywhere else, time values are computed according to the time offset of your " +"web client." +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "delivery date" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "scheduled date" +msgstr "" diff --git a/stock_partner_delivery_window/i18n/stock_partner_delivery_window.pot b/stock_partner_delivery_window/i18n/stock_partner_delivery_window.pot new file mode 100644 index 000000000000..c8cbe5b84154 --- /dev/null +++ b/stock_partner_delivery_window/i18n/stock_partner_delivery_window.pot @@ -0,0 +1,179 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_partner_delivery_window +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__anytime +msgid "Any time" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_res_partner +msgid "Contact" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_uid +msgid "Created by" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__create_date +msgid "Created on" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,help:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "" +"Define the scheduling preference for delivery orders:\n" +"\n" +"* Any time: Do not postpone deliveries\n" +"* Fixed time windows: Postpone deliveries to the next preferred time window\n" +"* Weekdays: Postpone deliveries to the next weekday" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_preference +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_preference +msgid "Delivery time schedule preference" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_partner__delivery_time_window_ids +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_res_users__delivery_time_window_ids +msgid "Delivery time windows" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__display_name +msgid "Display Name" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__time_windows +msgid "Fixed time windows" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_start +msgid "From" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__id +msgid "ID" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__write_date +msgid "Last Updated on" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"No %(date_name)s is set on the picking, cannot check if it is in partner's " +"delivery window." +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__partner_id +msgid "Partner" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_stock_picking__partner_delivery_window_warning +msgid "Partner Delivery Window Warning" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/res_partner.py:0 +msgid "" +"Please define at least one delivery time window or change preference to Any " +"time" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_partner_delivery_time_window +msgid "Preferred delivery time windows" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer deliveries on following time windows:\n" +"%(window)s" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "" +"The %(date_name)s is %(date)s (%(tz)s), but the partner is set to prefer " +"deliveries on working days." +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_weekday_ids +msgid "Time Window Weekday" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "Timezone" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,field_description:stock_partner_delivery_window.field_partner_delivery_time_window__time_window_end +msgid "To" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model,name:stock_partner_delivery_window.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields.selection,name:stock_partner_delivery_window.selection__res_partner__delivery_time_preference__workdays +msgid "Weekdays (Monday to Friday)" +msgstr "" + +#. module: stock_partner_delivery_window +#: model:ir.model.fields,help:stock_partner_delivery_window.field_partner_delivery_time_window__tz +msgid "" +"When printing documents and exporting/importing data, time values are computed according to this timezone.\n" +"If the timezone is not set, UTC (Coordinated Universal Time) is used.\n" +"Anywhere else, time values are computed according to the time offset of your web client." +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "delivery date" +msgstr "" + +#. module: stock_partner_delivery_window +#. odoo-python +#: code:addons/stock_partner_delivery_window/models/stock_picking.py:0 +msgid "scheduled date" +msgstr "" diff --git a/stock_partner_delivery_window/models/__init__.py b/stock_partner_delivery_window/models/__init__.py new file mode 100644 index 000000000000..2b3ebc04d451 --- /dev/null +++ b/stock_partner_delivery_window/models/__init__.py @@ -0,0 +1,3 @@ +from . import delivery_time_window +from . import res_partner +from . import stock_picking diff --git a/stock_partner_delivery_window/models/delivery_time_window.py b/stock_partner_delivery_window/models/delivery_time_window.py new file mode 100644 index 000000000000..c3abd1008b0e --- /dev/null +++ b/stock_partner_delivery_window/models/delivery_time_window.py @@ -0,0 +1,20 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo import api, fields, models + + +class DeliveryTimeWindow(models.Model): + _name = "partner.delivery.time.window" + _inherit = "time.window.mixin" + _description = "Preferred delivery time windows" + _time_window_overlap_check_field = "partner_id" + + partner_id = fields.Many2one( + "res.partner", required=True, index=True, ondelete="cascade" + ) + tz = fields.Selection(related="partner_id.tz") + + @api.constrains("partner_id") + def check_window_no_overlaps(self): + return super().check_window_no_overlaps() diff --git a/stock_partner_delivery_window/models/res_partner.py b/stock_partner_delivery_window/models/res_partner.py new file mode 100644 index 000000000000..42b4ce1a11e3 --- /dev/null +++ b/stock_partner_delivery_window/models/res_partner.py @@ -0,0 +1,131 @@ +# Copyright 2020 Camptocamp SA +# Copyright 2025 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +import datetime + +import pytz + +from odoo import Command, api, fields, models +from odoo.exceptions import ValidationError +from odoo.fields import Domain + +WORKDAYS = list(range(5)) + + +class ResPartner(models.Model): + _inherit = "res.partner" + + delivery_time_preference = fields.Selection( + [ + ("anytime", "Any time"), + ("time_windows", "Fixed time windows"), + ("workdays", "Weekdays (Monday to Friday)"), + ], + string="Delivery time schedule preference", + default="anytime", + required=True, + help="Define the scheduling preference for delivery orders:\n\n" + "* Any time: Do not postpone deliveries\n" + "* Fixed time windows: Postpone deliveries to the next preferred " + "time window\n" + "* Weekdays: Postpone deliveries to the next weekday", + ) + + delivery_time_window_ids = fields.One2many( + "partner.delivery.time.window", "partner_id", string="Delivery time windows" + ) + + @api.constrains("delivery_time_preference", "delivery_time_window_ids") + def _check_delivery_time_preference(self): + for partner in self: + if ( + partner.delivery_time_preference == "time_windows" + and not partner.delivery_time_window_ids + ): + raise ValidationError( + self.env._( + "Please define at least one delivery time window or change" + " preference to Any time" + ) + ) + + def _get_delivery_windows(self, day_name=None): + """ + Return the list of delivery windows by partner id for the given day + + :param day: The day name (see time.weekday, ex: 0,1,2,...) + :return: dict partner: delivery_window recordset + """ + domain = Domain("partner_id", "in", self.ids) + if day_name is not None: + week_day_id = self.env["time.weekday"]._get_id_by_name(day_name) + domain &= Domain("time_window_weekday_ids", "in", [week_day_id]) + windows = self.env["partner.delivery.time.window"].search(domain) + return windows.grouped("partner_id") + + @property + def delivery_time_weekdays(self): + if not self: # pragma: no cover + return set() + self.ensure_one() + if self.delivery_time_preference == "anytime": + weekdays = set(range(7)) + elif self.delivery_time_preference == "workdays": + weekdays = set(range(5)) + else: + weekdays = set( + map( + int, + self.delivery_time_window_ids.time_window_weekday_ids.mapped( + "name" + ), + ) + ) + return weekdays + + def _is_in_delivery_window(self, date): + """ + Checks if provided date is in a delivery window for actual partner + + :param date: Datetime or Date object + :return: Boolean + """ + self.ensure_one() + tz = pytz.timezone(self.tz or self.env.company.partner_id.tz or "UTC") + if isinstance(date, datetime.datetime): + date = date.astimezone(pytz.utc).astimezone(tz) + if self.delivery_time_preference == "workdays": + if date.weekday() > 4: + return False + return True + windows = self._get_delivery_windows(date.weekday()).get(self) + if windows: + if not isinstance(date, datetime.datetime): + return True + for w in windows: + start_time = w.get_time_window_start_time() + end_time = w.get_time_window_end_time() + if start_time <= date.time() <= end_time: + return True + return False + + def copy_data(self, default=None): + result = super().copy_data(default=default)[0] + not_time_windows = self.delivery_time_preference != "time_windows" + not_copy_windows = not_time_windows or "delivery_time_window_ids" in result + if not_copy_windows: + return [result] + values = [ + { + "time_window_start": window_id.time_window_start, + "time_window_end": window_id.time_window_end, + "time_window_weekday_ids": [ + Command.link(wd_id.id) + for wd_id in window_id.time_window_weekday_ids + ], + } + for window_id in self.delivery_time_window_ids + ] + result["delivery_time_window_ids"] = [Command.create(val) for val in values] + return [result] diff --git a/stock_partner_delivery_window/models/stock_picking.py b/stock_partner_delivery_window/models/stock_picking.py new file mode 100644 index 000000000000..d678e44858e8 --- /dev/null +++ b/stock_partner_delivery_window/models/stock_picking.py @@ -0,0 +1,87 @@ +# Copyright 2020 Camptocamp SA +# Copyright 2025 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +import datetime + +from odoo import api, fields, models +from odoo.tools.misc import format_date, format_datetime + + +class StockPicking(models.Model): + _inherit = "stock.picking" + + partner_delivery_window_warning = fields.Text( + compute="_compute_partner_delivery_window_warning" + ) + + def _planned_delivery_date(self): + return self.scheduled_date + + @property + def _planned_delivery_date_name(self): + return ( + self.env._("scheduled date") + if self._planned_delivery_date() == self.scheduled_date + else self.env._("delivery date") + ) + + @api.depends("partner_id", "scheduled_date") + def _compute_partner_delivery_window_warning(self): + for picking in self: + partner = picking.partner_id + picking.partner_delivery_window_warning = False + if not partner: # pragma: no cover + continue + + anytime_delivery = partner and partner.delivery_time_preference == "anytime" + not_outgoing_picking = picking.picking_type_id.code != "outgoing" + + delivery_date = picking._planned_delivery_date() + + if anytime_delivery or not_outgoing_picking: + continue + + elif not delivery_date: + picking.partner_delivery_window_warning = self.env._( + "No %(date_name)s is set on the picking, cannot check " + "if it is in partner's delivery window.", + date_name=picking._planned_delivery_date_name, + ) + + elif not partner._is_in_delivery_window(delivery_date): + picking.partner_delivery_window_warning = ( + picking._scheduled_date_no_delivery_window_match_msg() + ) + + def _scheduled_date_no_delivery_window_match_msg(self): + delivery_date = self._planned_delivery_date() + if isinstance(delivery_date, datetime.datetime): + formatted_delivery_date = format_datetime(self.env, delivery_date) + else: + formatted_delivery_date = format_date(self.env, delivery_date) + partner = self.partner_id + if partner.delivery_time_preference == "workdays": + message = self.env._( + "The %(date_name)s is %(date)s (%(tz)s), but the partner is " + "set to prefer deliveries on working days.", + date_name=self._planned_delivery_date_name, + date=formatted_delivery_date, + tz=self.env.context.get("tz"), + ) + else: + delivery_windows_strings = [] + if partner: + for w in partner._get_delivery_windows().get(partner): + delivery_windows_strings.append( + f" * {w.display_name} ({partner.tz})" + ) + message = self.env._( + "The %(date_name)s is %(date)s (%(tz)s), but the partner is " + "set to prefer deliveries on following time windows:\n%(window)s", + date_name=self._planned_delivery_date_name, + date=formatted_delivery_date, + tz=self.env.context.get("tz"), + window="\n".join(delivery_windows_strings), + ) + return message diff --git a/stock_partner_delivery_window/pyproject.toml b/stock_partner_delivery_window/pyproject.toml new file mode 100644 index 000000000000..4231d0cccb3d --- /dev/null +++ b/stock_partner_delivery_window/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/stock_partner_delivery_window/readme/CONFIGURE.md b/stock_partner_delivery_window/readme/CONFIGURE.md new file mode 100644 index 000000000000..5ba9f55c4931 --- /dev/null +++ b/stock_partner_delivery_window/readme/CONFIGURE.md @@ -0,0 +1,12 @@ +On partners form view, under the "Sales & Purchases" tab, one can define +a "Delivery schedule preference" for each partner. + +Possible configurations are: + +- Any time: Do not postpone deliveries +- Fixed time windows: Postpone deliveries to the next preferred time + window +- Weekdays: Postpone deliveries to the next weekday + +After selecting "Fixed time windows", one can define the preferred +delivery windows in the embedded tree view below. diff --git a/stock_partner_delivery_window/readme/CONTRIBUTORS.md b/stock_partner_delivery_window/readme/CONTRIBUTORS.md new file mode 100644 index 000000000000..206ea57a328c --- /dev/null +++ b/stock_partner_delivery_window/readme/CONTRIBUTORS.md @@ -0,0 +1,9 @@ +- Akim Juillerat \<\> +- Iván Todorovich \<\> +- Matthieu Méquignon \<\> +- Jacques-Etienne Baudoux (BCIM) \<\> + +Trobz + +- Dung Tran \<\> +- Vo Hong Thien \<\> diff --git a/stock_partner_delivery_window/readme/CREDITS.md b/stock_partner_delivery_window/readme/CREDITS.md new file mode 100644 index 000000000000..6dd443011c40 --- /dev/null +++ b/stock_partner_delivery_window/readme/CREDITS.md @@ -0,0 +1,5 @@ +The development of this module has been financially supported by: + +- Camptocamp + +The migration of this module from 16.0 to 18.0 was financially supported by Camptocamp. diff --git a/stock_partner_delivery_window/readme/DESCRIPTION.md b/stock_partner_delivery_window/readme/DESCRIPTION.md new file mode 100644 index 000000000000..b3cfb4f28a75 --- /dev/null +++ b/stock_partner_delivery_window/readme/DESCRIPTION.md @@ -0,0 +1,3 @@ +This module allows to define time scheduling preference for delivery +orders on partners, in order to raise a warning when changing a +scheduled date to a time window that is not preferred by this customer. diff --git a/stock_partner_delivery_window/security/ir.model.access.csv b/stock_partner_delivery_window/security/ir.model.access.csv new file mode 100644 index 000000000000..096e52b6582f --- /dev/null +++ b/stock_partner_delivery_window/security/ir.model.access.csv @@ -0,0 +1,3 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +access_partner_delivery_time_window_user,access_partner_delivery_time_window_user,model_partner_delivery_time_window,base.group_user,1,0,0,0 +access_partner_delivery_time_window_manager,access_partner_delivery_time_window_manager,model_partner_delivery_time_window,stock.group_stock_manager,1,1,1,1 diff --git a/stock_partner_delivery_window/static/description/icon.png b/stock_partner_delivery_window/static/description/icon.png new file mode 100644 index 000000000000..3a0328b516c4 Binary files /dev/null and b/stock_partner_delivery_window/static/description/icon.png differ diff --git a/stock_partner_delivery_window/static/description/index.html b/stock_partner_delivery_window/static/description/index.html new file mode 100644 index 000000000000..7babfc328ab7 --- /dev/null +++ b/stock_partner_delivery_window/static/description/index.html @@ -0,0 +1,468 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Stock Partner Delivery Window

+ +

Beta License: AGPL-3 OCA/stock-logistics-workflow Translate me on Weblate Try me on Runboat

+

This module allows to define time scheduling preference for delivery +orders on partners, in order to raise a warning when changing a +scheduled date to a time window that is not preferred by this customer.

+

Table of contents

+ +
+

Configuration

+

On partners form view, under the “Sales & Purchases” tab, one can define +a “Delivery schedule preference” for each partner.

+

Possible configurations are:

+
    +
  • Any time: Do not postpone deliveries
  • +
  • Fixed time windows: Postpone deliveries to the next preferred time +window
  • +
  • Weekdays: Postpone deliveries to the next weekday
  • +
+

After selecting “Fixed time windows”, one can define the preferred +delivery windows in the embedded tree view below.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
  • ACSONE SA/NV
  • +
  • BCIM
  • +
+
+
+

Contributors

+ +

Trobz

+ +
+
+

Other credits

+

The development of this module has been financially supported by:

+
    +
  • Camptocamp
  • +
+

The migration of this module from 16.0 to 18.0 was financially supported +by Camptocamp.

+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

Current maintainer:

+

jbaudoux

+

This module is part of the OCA/stock-logistics-workflow project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/stock_partner_delivery_window/tests/__init__.py b/stock_partner_delivery_window/tests/__init__.py new file mode 100644 index 000000000000..5f68a6760103 --- /dev/null +++ b/stock_partner_delivery_window/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_delivery_window +from . import test_delivery_window_date diff --git a/stock_partner_delivery_window/tests/common.py b/stock_partner_delivery_window/tests/common.py new file mode 100644 index 000000000000..8806899ccaff --- /dev/null +++ b/stock_partner_delivery_window/tests/common.py @@ -0,0 +1,61 @@ +# Copyright 2020 Camptocamp +# Copyright 2025 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.addons.base.tests.common import BaseCommon + + +class PartnerDeliveryWindowCommon(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.customer_anytime = cls.env["res.partner"].create( + {"name": "Anytime", "delivery_time_preference": "anytime"} + ) + cls.customer_working_days = cls.env["res.partner"].create( + {"name": "Working Days", "delivery_time_preference": "workdays"} + ) + cls.customer_time_window = cls.env["res.partner"].create( + { + "name": "Time Window", + "delivery_time_preference": "time_windows", + "delivery_time_window_ids": [ + ( + 0, + 0, + { + "time_window_start": 0.00, + "time_window_end": 23.99, + "time_window_weekday_ids": [ + ( + 6, + 0, + [ + cls.env.ref( + "base_time_window.time_weekday_thursday" + ).id, + cls.env.ref( + "base_time_window.time_weekday_saturday" + ).id, + ], + ) + ], + }, + ) + ], + } + ) + cls.product = cls.env["product.product"].create({"name": "Test product"}) + cls.picking_type_delivery = cls.env.ref("stock.picking_type_out") + cls.location_stock = cls.env.ref("stock.stock_location_stock") + cls.location_customers = cls.env.ref("stock.stock_location_customers") + + def _create_delivery_picking(cls, partner): + return cls.env["stock.picking"].create( + { + "partner_id": partner.id, + "location_id": cls.location_stock.id, + "location_dest_id": cls.location_customers.id, + "picking_type_id": cls.picking_type_delivery.id, + } + ) diff --git a/stock_partner_delivery_window/tests/test_delivery_window.py b/stock_partner_delivery_window/tests/test_delivery_window.py new file mode 100644 index 000000000000..0150f527c265 --- /dev/null +++ b/stock_partner_delivery_window/tests/test_delivery_window.py @@ -0,0 +1,265 @@ +# Copyright 2020 Camptocamp +# Copyright 2025 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import datetime +from unittest import mock + +from freezegun import freeze_time + +from .common import PartnerDeliveryWindowCommon + + +class TestPartnerDeliveryWindow(PartnerDeliveryWindowCommon): + @freeze_time("2020-04-02") # Thursday + def test_delivery_window_warning(self): + # No warning with anytime + anytime_picking = self._create_delivery_picking(self.customer_anytime) + anytime_picking.scheduled_date = "2020-04-03" # Friday + anytime_picking._compute_partner_delivery_window_warning() + self.assertFalse(anytime_picking.partner_delivery_window_warning) + # No warning on friday + workdays_picking = self._create_delivery_picking(self.customer_working_days) + workdays_picking.scheduled_date = "2020-04-03" # Friday + workdays_picking._compute_partner_delivery_window_warning() + self.assertFalse(workdays_picking.partner_delivery_window_warning) + # But warning on saturday + workdays_picking.scheduled_date = "2020-04-04" # Saturday + workdays_picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on working days", + workdays_picking.partner_delivery_window_warning, + ) + # No warning on preferred time window + time_window_picking = self._create_delivery_picking(self.customer_time_window) + time_window_picking.scheduled_date = "2020-04-04" # Saturday + time_window_picking._compute_partner_delivery_window_warning() + self.assertFalse(time_window_picking.partner_delivery_window_warning) + time_window_picking.scheduled_date = "2020-04-03" # Friday + time_window_picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + time_window_picking.partner_delivery_window_warning, + ) + # Warning when no scheduled date + with mock.patch( + "odoo.addons.stock_partner_delivery_window.models.stock_picking.StockPicking._planned_delivery_date", + return_value=False, + ): + time_window_picking._compute_partner_delivery_window_warning() + self.assertIn( + "No delivery date is set on the picking, cannot check", + time_window_picking.partner_delivery_window_warning, + ) + + @freeze_time("2020-04-02") + def test_with_timezone_dst_date_dst(self): + """Test while we are in DST and scheduled date also in DST""" + # Define customer to allow shipping only between 10.00am and 4.00pm + # in tz 'Europe/Brussels' (UTC+1 or UTC+2 during DST) + self.customer_time_window.tz = "Europe/Brussels" + self.customer_time_window.delivery_time_window_ids.write( + {"time_window_start": 10.0, "time_window_end": 16.0} + ) + picking = self._create_delivery_picking(self.customer_time_window) + # Frozen time is in UTC so 2020-04-02 07:59:59 == 2020-04-02 09:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 07:59:59" # Thursday + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + # Scheduled date is in UTC so 2020-04-02 08:00:00 == 2020-04-02 10:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 08:00:00" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-04-02 13:59:59 == 2020-04-02 15:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 13:59:59" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-04-02 14:00:00 == 2020-04-02 16:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 14:00:00" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-04-02 14:00:01 == 2020-04-02 16:00:01 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 14:00:01" + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + + @freeze_time("2020-03-26") + def test_with_timezone_no_dst_date_no_dst(self): + """Test while we are not in DST and scheduled date also not in DST""" + # Define customer to allow shipping only between 10.00am and 4.00pm + # in tz 'Europe/Brussels' (UTC+1 or UTC+2 during DST) + self.customer_time_window.tz = "Europe/Brussels" + self.customer_time_window.delivery_time_window_ids.write( + {"time_window_start": 10.0, "time_window_end": 16.0} + ) + picking = self._create_delivery_picking(self.customer_time_window) + # Frozen time is in UTC so 2020-03-26 08:59:59 == 2020-04-02 09:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 08:59:59" # Thursday + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + # Scheduled date is in UTC so 2020-03-26 09:00:00 == 2020-04-02 10:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 09:00:00" + picking._compute_partner_delivery_window_warning() + # No warning since we're in the timeframe + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-03-26 14:59:59 == 2020-04-02 15:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 14:59:59" + picking._compute_partner_delivery_window_warning() + # No warning since we're in the timeframe + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-03-26 15:00:00 == 2020-04-02 16:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 15:00:00" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-03-26 15:00:01 == 2020-04-02 16:00:01 + # in Brussels which is not preferred + picking.scheduled_date = "2020-03-26 15:00:01" + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + + @freeze_time("2020-03-26") + def test_with_timezone_no_dst_date_dst(self): + """Test while we are not in DST and scheduled date is in DST""" + # Define customer to allow shipping only between 10.00am and 4.00pm + # in tz 'Europe/Brussels' (UTC+1 or UTC+2 during DST) + self.customer_time_window.tz = "Europe/Brussels" + self.customer_time_window.delivery_time_window_ids.write( + {"time_window_start": 10.0, "time_window_end": 16.0} + ) + picking = self._create_delivery_picking(self.customer_time_window) + # Frozen time is in UTC so 2020-04-02 07:59:59 == 2020-04-02 09:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 07:59:59" # Thursday + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + # Scheduled date is in UTC so 2020-04-02 08:00:00 == 2020-04-02 10:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 08:00:00" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-04-02 13:59:59 == 2020-04-02 15:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 13:59:59" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-04-02 14:00:00 == 2020-04-02 16:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 14:00:00" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-04-02 14:00:01 == 2020-04-02 16:00:01 + # in Brussels which is preferred + picking.scheduled_date = "2020-04-02 14:00:01" + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + # Now test with a scheduled that is not in DST + + @freeze_time("2020-04-02") + def test_with_timezone_dst_date_no_dst(self): + """Test while we are in DST and scheduled date not in DST""" + # Define customer to allow shipping only between 10.00am and 4.00pm + # in tz 'Europe/Brussels' (UTC+1 or UTC+2 during DST) + self.customer_time_window.tz = "Europe/Brussels" + self.customer_time_window.delivery_time_window_ids.write( + {"time_window_start": 10.0, "time_window_end": 16.0} + ) + picking = self._create_delivery_picking(self.customer_time_window) + # Frozen time is in UTC so 2020-03-26 08:59:59 == 2020-04-02 09:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 08:59:59" # Thursday + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + # Scheduled date is in UTC so 2020-03-26 09:00:00 == 2020-04-02 10:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 09:00:00" + picking._compute_partner_delivery_window_warning() + # No warning since we're in the timeframe + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-03-26 14:59:59 == 2020-04-02 15:59:59 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 14:59:59" + picking._compute_partner_delivery_window_warning() + # No warning since we're in the timeframe + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-03-26 15:00:00 == 2020-04-02 16:00:00 + # in Brussels which is preferred + picking.scheduled_date = "2020-03-26 15:00:00" + picking._compute_partner_delivery_window_warning() + self.assertFalse(picking.partner_delivery_window_warning) + # Scheduled date is in UTC so 2020-03-26 15:00:01 == 2020-04-02 16:00:01 + # in Brussels which is not preferred + picking.scheduled_date = "2020-03-26 15:00:01" + picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + picking.partner_delivery_window_warning, + ) + + def test_copy_partner_with_time_window_ids(self): + copied_partner = self.customer_time_window.copy() + expecting = len(self.customer_time_window.delivery_time_window_ids) + self.assertEqual(len(copied_partner.delivery_time_window_ids), expecting) + copied_partner = self.customer_working_days.copy() + self.assertFalse(copied_partner.delivery_time_window_ids) + + def test_weekdays_anytime(self): + self.assertEqual( + self.customer_anytime.delivery_time_weekdays, {0, 1, 2, 3, 4, 5, 6} + ) + + def test_weekdays_working_days(self): + self.assertEqual( + self.customer_working_days.delivery_time_weekdays, {0, 1, 2, 3, 4} + ) + + def test_weekdays_time_window(self): + self.assertEqual(self.customer_time_window.delivery_time_weekdays, {3, 5}) + + def test_is_in_delivery_window(self): + # window for Thu and Sat + self.customer_time_window.delivery_time_window_ids.write( + {"time_window_start": 10.0, "time_window_end": 16.0} + ) + # Friday + date = datetime.date.fromisoformat("2020-04-03") + self.assertFalse(self.customer_time_window._is_in_delivery_window(date)) + # Saturday + date = datetime.date.fromisoformat("2020-04-04") + self.assertTrue(self.customer_time_window._is_in_delivery_window(date)) + date = datetime.datetime.fromisoformat("2020-04-04 09:00:00") + self.assertFalse(self.customer_time_window._is_in_delivery_window(date)) + date = datetime.datetime.fromisoformat("2020-04-04 10:00:00") + self.assertTrue(self.customer_time_window._is_in_delivery_window(date)) + date = datetime.datetime.fromisoformat("2020-04-04 16:00:00") + self.assertTrue(self.customer_time_window._is_in_delivery_window(date)) + date = datetime.datetime.fromisoformat("2020-04-04 17:00:00") + self.assertFalse(self.customer_time_window._is_in_delivery_window(date)) diff --git a/stock_partner_delivery_window/tests/test_delivery_window_date.py b/stock_partner_delivery_window/tests/test_delivery_window_date.py new file mode 100644 index 000000000000..31abfd8c189c --- /dev/null +++ b/stock_partner_delivery_window/tests/test_delivery_window_date.py @@ -0,0 +1,61 @@ +# Copyright 2025 Jacques-Etienne Baudoux (BCIM) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from unittest import mock + +from freezegun import freeze_time + +from .common import PartnerDeliveryWindowCommon + + +class TestPartnerDeliveryWindowDate(PartnerDeliveryWindowCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.startClassPatcher( + mock.patch( + "odoo.addons.stock_partner_delivery_window.models.stock_picking.StockPicking._planned_delivery_date", + new=lambda self: self.scheduled_date and self.scheduled_date.date(), + ) + ) + + @freeze_time("2020-04-02") # Thursday + def test_delivery_window_warning(self): + # No warning with anytime + anytime_picking = self._create_delivery_picking(self.customer_anytime) + anytime_picking.scheduled_date = "2020-04-03" # Friday + anytime_picking._compute_partner_delivery_window_warning() + self.assertFalse(anytime_picking.partner_delivery_window_warning) + # No warning on friday + workdays_picking = self._create_delivery_picking(self.customer_working_days) + workdays_picking.scheduled_date = "2020-04-03" # Friday + workdays_picking._compute_partner_delivery_window_warning() + self.assertFalse(workdays_picking.partner_delivery_window_warning) + # But warning on saturday + workdays_picking.scheduled_date = "2020-04-04" # Saturday + workdays_picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on working days", + workdays_picking.partner_delivery_window_warning, + ) + # No warning on preferred time window + time_window_picking = self._create_delivery_picking(self.customer_time_window) + time_window_picking.scheduled_date = "2020-04-04" # Saturday + time_window_picking._compute_partner_delivery_window_warning() + self.assertFalse(time_window_picking.partner_delivery_window_warning) + time_window_picking.scheduled_date = "2020-04-03" # Friday + time_window_picking._compute_partner_delivery_window_warning() + self.assertIn( + "the partner is set to prefer deliveries on following time windows", + time_window_picking.partner_delivery_window_warning, + ) + # Warning when no scheduled date + with mock.patch( + "odoo.addons.stock_partner_delivery_window.models.stock_picking.StockPicking._planned_delivery_date", + return_value=False, + ): + time_window_picking._compute_partner_delivery_window_warning() + self.assertIn( + "No delivery date is set on the picking, cannot check", + time_window_picking.partner_delivery_window_warning, + ) diff --git a/stock_partner_delivery_window/views/res_partner.xml b/stock_partner_delivery_window/views/res_partner.xml new file mode 100644 index 000000000000..be89331655aa --- /dev/null +++ b/stock_partner_delivery_window/views/res_partner.xml @@ -0,0 +1,29 @@ + + + + res.partner.form.inherit + res.partner + + + + +
+
+
+
+
+
diff --git a/stock_partner_delivery_window/views/stock_picking_view.xml b/stock_partner_delivery_window/views/stock_picking_view.xml new file mode 100644 index 000000000000..a5f9bc2b5975 --- /dev/null +++ b/stock_partner_delivery_window/views/stock_picking_view.xml @@ -0,0 +1,23 @@ + + + + stock.picking.form.inherit + stock.picking + + + + + + + + diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000000..78ec5d5bf88b --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +odoo-addon-partner_tz @ git+https://github.com/OCA/partner-contact.git@refs/pull/2252/head#subdirectory=partner_tz +odoo-addon-base_time_window @ git+https://github.com/OCA/server-tools.git@refs/pull/3490/head#subdirectory=base_time_window