diff --git a/setup/website_sale_commitment_date/odoo/addons/website_sale_commitment_date b/setup/website_sale_commitment_date/odoo/addons/website_sale_commitment_date new file mode 120000 index 0000000000..2ac8603dc9 --- /dev/null +++ b/setup/website_sale_commitment_date/odoo/addons/website_sale_commitment_date @@ -0,0 +1 @@ +../../../../website_sale_commitment_date \ No newline at end of file diff --git a/setup/website_sale_commitment_date/setup.py b/setup/website_sale_commitment_date/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/website_sale_commitment_date/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/website_sale_commitment_date/README.rst b/website_sale_commitment_date/README.rst new file mode 100644 index 0000000000..1ade632e60 --- /dev/null +++ b/website_sale_commitment_date/README.rst @@ -0,0 +1,92 @@ +============================ +Website Sale Commitment Date +============================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:70c786255989ea550c4a2717056ac5be90a46d847d4d13bab338daefb3f41453 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fe--commerce-lightgray.png?logo=github + :target: https://github.com/OCA/e-commerce/tree/16.0/website_sale_commitment_date + :alt: OCA/e-commerce +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/e-commerce-16-0/e-commerce-16-0-website_sale_commitment_date + :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/e-commerce&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon allows selecting the delivery date when purchasing from the e-commerce platform, +configuring excluded days of the week, minimum or maximum days to limit the selection +from the current date. All of this is configurable from the shipping method. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + + +To use this addon, you need to go to the shipping method and activate the "allow commitment date" option. +Then, you can configure various settings right there. Afterward, +go to the cart in the e-commerce platform, and you will see that if you select that shipping method, +the option to choose the delivery day will appear. +When using a shipping method that requires specifying the delivery date, +the button will not appear until a date is selected. + + +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 +~~~~~~~ + +* Binhex + +Contributors +~~~~~~~~~~~~ + +* `Binhex `_: + + * Adasat Torres de León + +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/e-commerce `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_sale_commitment_date/__init__.py b/website_sale_commitment_date/__init__.py new file mode 100644 index 0000000000..7dc6d0e89e --- /dev/null +++ b/website_sale_commitment_date/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import models +from . import controllers diff --git a/website_sale_commitment_date/__manifest__.py b/website_sale_commitment_date/__manifest__.py new file mode 100644 index 0000000000..8b4e8da081 --- /dev/null +++ b/website_sale_commitment_date/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Website Sale Commitment Date", + "version": "16.0.1.0.0", + "category": "Website", + "author": "Binhex, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/e-commerce", + "license": "AGPL-3", + "summary": "Allow to set a commitment date on the sale order from to the e-commerce", + "depends": ["website_sale_delivery"], + "data": [ + "security/ir.model.access.csv", + "views/delivery_carrier_views.xml", + "views/delivery_carrier_templates.xml", + "data/delivery_carrier_weekday_data.xml", + ], + "assets": { + "web.assets_frontend": [ + "website_sale_commitment_date/static/src/**/*", + ], + }, +} diff --git a/website_sale_commitment_date/controllers/__init__.py b/website_sale_commitment_date/controllers/__init__.py new file mode 100644 index 0000000000..12a7e529b6 --- /dev/null +++ b/website_sale_commitment_date/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_sale_commitment_date/controllers/main.py b/website_sale_commitment_date/controllers/main.py new file mode 100644 index 0000000000..2a2c1bf140 --- /dev/null +++ b/website_sale_commitment_date/controllers/main.py @@ -0,0 +1,88 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import logging +from datetime import datetime + +from dateutil.relativedelta import relativedelta + +from odoo import http +from odoo.http import request +from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, format_date + +from odoo.addons.website_sale_delivery.controllers.main import WebsiteSaleDelivery + +_logger = logging.getLogger(__name__) + + +class WebsiteSaleCommitmentDate(WebsiteSaleDelivery): + @http.route() + def payment(self, **post): + res = super().payment(**post) + order = request.website.sale_get_order() + if order and order.carrier_id: + res.qcontext.update( + "allow_commitment_date", order.carrier_id.allow_commitment_date + ) + return res + + @http.route( + "/shop/update_commitment_date", type="json", auth="public", website=True + ) + def update_commitment_date(self, **post): + order = request.website.sale_get_order() + string_date = post.get("date") + lang = request.env["res.lang"]._lang_get( + request.env.context.get("lang", False) or request.env.user.lang + ) + if order: + date_obj = datetime.strptime( + string_date, + lang.date_format if lang else DEFAULT_SERVER_DATE_FORMAT, + ) + order.commitment_date = date_obj + return { + "success": order.commitment_date.date() == date_obj.date(), + "date": format_date(request.env, date_obj.date()), + } + + @http.route() + def update_eshop_carrier(self, **post): + res = super().update_eshop_carrier(**post) + order = request.website.sale_get_order() + if order.carrier_id and not order.carrier_id.allow_commitment_date: + order.commitment_date = False + return res + + def _update_website_sale_delivery_return(self, order, **post): + res = super()._update_website_sale_delivery_return(order, **post) + if order and order.carrier_id: + res["allow_commitment_date"] = order.carrier_id.allow_commitment_date + return res + + @http.route("/calendar/commitment_date", type="json", auth="public", website=True) + def commitment_date(self, **post): + order = request.website.sale_get_order() + carrier = order.carrier_id + value = {} + lang = request.env["res.lang"]._lang_get( + request.env.context.get("lang", False) or request.env.user.lang + ) + action = post.get("action", False) + start = post.get("start", False) + if start: + start = datetime.strptime( + start, lang.date_format if lang else DEFAULT_SERVER_DATE_FORMAT + ).date() + + if carrier: + if action == "prev": + value = carrier._get_calendar_context( + start=start - relativedelta(months=1) + ) + elif action == "next": + value = carrier._get_calendar_context( + start=start + relativedelta(months=1) + ) + else: + value = carrier._get_calendar_context() + return value diff --git a/website_sale_commitment_date/data/delivery_carrier_weekday_data.xml b/website_sale_commitment_date/data/delivery_carrier_weekday_data.xml new file mode 100644 index 0000000000..c3cefd7508 --- /dev/null +++ b/website_sale_commitment_date/data/delivery_carrier_weekday_data.xml @@ -0,0 +1,31 @@ + + + + Monday + 0 + + + Tuesday + 1 + + + Wednesday + 2 + + + Thursday + 3 + + + Friday + 4 + + + Saturday + 5 + + + Sunday + 6 + + diff --git a/website_sale_commitment_date/i18n/es.po b/website_sale_commitment_date/i18n/es.po new file mode 100644 index 0000000000..6ed81c08ac --- /dev/null +++ b/website_sale_commitment_date/i18n/es.po @@ -0,0 +1,233 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_commitment_date +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0-20240429\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-01-13 20:08+0000\n" +"PO-Revision-Date: 2025-01-13 20:08+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.4.4\n" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid " Calendar" +msgstr " Calendario" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "" +"\n" +" \n" +" The commitment date is the date when the " +"order will be delivered to you.\n" +"
\n" +" Please select a date that is convenient " +"for you.\n" +"
\n" +" Select a commitment date before completing " +"the order.\n" +"
\n" +"
" +msgstr "" +"\n" +" \n" +" La fecha de entrega es la fecha en la que " +"se le entregará el pedido.\n" +"
\n" +" Seleccione la fecha que más le convenga.\n" +"
\n" +" Seleccione una fecha de entrega antes de " +"completar el pedido.\n" +"
\n" +"
" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__allow_commitment_date +msgid "Allow commitment date" +msgstr "Permitir fecha de entrega" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,help:website_sale_commitment_date.field_delivery_carrier__allow_commitment_date +msgid "" +"Allow to set a commitment date on the sale order from to the e-commerce" +msgstr "" +"Permitir fijar una fecha de entrega en la orden de venta al comercio " +"electrónico" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "Calendar" +msgstr "Calendario" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "Close" +msgstr "Cerrar" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.delivery_carrier_view_form_inherit +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.payment +msgid "Commitment Date" +msgstr "Fecha de entrega" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "Confirm" +msgstr "Confirmar" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__create_uid +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__create_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__value +msgid "Date" +msgstr "Fecha" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__display_name +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: website_sale_commitment_date +#: model:ir.actions.act_window,name:website_sale_commitment_date.action_open_commitment_date_exclude +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__exclude_date_ids +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.delivery_carrier_view_form_inherit +msgid "Exclude Dates" +msgstr "Fechas a excluir" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__exclude_weekday_ids +msgid "Exclude Weekdays" +msgstr "Excluir días" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.friday_weekday +msgid "Friday" +msgstr "Viernes" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__id +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__id +msgid "ID" +msgstr "ID" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__name +msgid "Label" +msgstr "Etiqueta" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date____last_update +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__write_uid +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__write_uid +msgid "Last Updated by" +msgstr "Actualizado por última vez por" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__write_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__max_commitment_days +msgid "Max Commitment Days" +msgstr "Maximo de días para la fecha de entrega" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__min_commitment_days +msgid "Min Commitment Days" +msgstr "Mínimo de días para la fecha de entrega" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.monday_weekday +msgid "Monday" +msgstr "Lunes" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__name +msgid "Name" +msgstr "Nombre" + +#. module: website_sale_commitment_date +#. odoo-javascript +#: code:addons/website_sale_commitment_date/static/src/xml/website_calendar.xml:0 +#, python-format +msgid "Next month" +msgstr "Mes siguiente" + +#. module: website_sale_commitment_date +#. odoo-javascript +#: code:addons/website_sale_commitment_date/static/src/xml/website_calendar.xml:0 +#, python-format +msgid "Previous month" +msgstr "Mes anterior" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.saturday_weekday +msgid "Saturday" +msgstr "Sábado" + +#. module: website_sale_commitment_date +#: model:ir.model,name:website_sale_commitment_date.model_delivery_carrier +msgid "Shipping Methods" +msgstr "Métodos de envío" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.sunday_weekday +msgid "Sunday" +msgstr "Domingo" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.thursday_weekday +msgid "Thursday" +msgstr "Jueves" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.tuesday_weekday +msgid "Tuesday" +msgstr "Martes" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__value +msgid "Value" +msgstr "Valor" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.wednesday_weekday +msgid "Wednesday" +msgstr "Miércoles" + +#. module: website_sale_commitment_date +#: model:ir.model,name:website_sale_commitment_date.model_delivery_carrier_date +msgid "delivery.carrier.date" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model,name:website_sale_commitment_date.model_delivery_carrier_weekday +msgid "delivery.carrier.weekday" +msgstr "" diff --git a/website_sale_commitment_date/i18n/website_sale_commitment_date.pot b/website_sale_commitment_date/i18n/website_sale_commitment_date.pot new file mode 100644 index 0000000000..71efc62c38 --- /dev/null +++ b/website_sale_commitment_date/i18n/website_sale_commitment_date.pot @@ -0,0 +1,215 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_commitment_date +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0-20240429\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-01-13 20:07+0000\n" +"PO-Revision-Date: 2025-01-13 20:07+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid " Calendar" +msgstr "" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "" +"\n" +" \n" +" The commitment date is the date when the order will be delivered to you.\n" +"
\n" +" Please select a date that is convenient for you.\n" +"
\n" +" Select a commitment date before completing the order.\n" +"
\n" +"
" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__allow_commitment_date +msgid "Allow commitment date" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,help:website_sale_commitment_date.field_delivery_carrier__allow_commitment_date +msgid "" +"Allow to set a commitment date on the sale order from to the e-commerce" +msgstr "" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "Calendar" +msgstr "" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "Close" +msgstr "" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.delivery_carrier_view_form_inherit +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.payment +msgid "Commitment Date" +msgstr "" + +#. module: website_sale_commitment_date +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.commitment_calendar +msgid "Confirm" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__create_uid +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__create_uid +msgid "Created by" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__create_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__create_date +msgid "Created on" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__value +msgid "Date" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__display_name +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__display_name +msgid "Display Name" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.actions.act_window,name:website_sale_commitment_date.action_open_commitment_date_exclude +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__exclude_date_ids +#: model_terms:ir.ui.view,arch_db:website_sale_commitment_date.delivery_carrier_view_form_inherit +msgid "Exclude Dates" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__exclude_weekday_ids +msgid "Exclude Weekdays" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.friday_weekday +msgid "Friday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__id +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__id +msgid "ID" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__name +msgid "Label" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date____last_update +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday____last_update +msgid "Last Modified on" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__write_uid +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_date__write_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__write_date +msgid "Last Updated on" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__max_commitment_days +msgid "Max Commitment Days" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier__min_commitment_days +msgid "Min Commitment Days" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.monday_weekday +msgid "Monday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__name +msgid "Name" +msgstr "" + +#. module: website_sale_commitment_date +#. odoo-javascript +#: code:addons/website_sale_commitment_date/static/src/xml/website_calendar.xml:0 +#, python-format +msgid "Next month" +msgstr "" + +#. module: website_sale_commitment_date +#. odoo-javascript +#: code:addons/website_sale_commitment_date/static/src/xml/website_calendar.xml:0 +#, python-format +msgid "Previous month" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.saturday_weekday +msgid "Saturday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model,name:website_sale_commitment_date.model_delivery_carrier +msgid "Shipping Methods" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.sunday_weekday +msgid "Sunday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.thursday_weekday +msgid "Thursday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.tuesday_weekday +msgid "Tuesday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model.fields,field_description:website_sale_commitment_date.field_delivery_carrier_weekday__value +msgid "Value" +msgstr "" + +#. module: website_sale_commitment_date +#: model:delivery.carrier.weekday,name:website_sale_commitment_date.wednesday_weekday +msgid "Wednesday" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model,name:website_sale_commitment_date.model_delivery_carrier_date +msgid "delivery.carrier.date" +msgstr "" + +#. module: website_sale_commitment_date +#: model:ir.model,name:website_sale_commitment_date.model_delivery_carrier_weekday +msgid "delivery.carrier.weekday" +msgstr "" diff --git a/website_sale_commitment_date/models/__init__.py b/website_sale_commitment_date/models/__init__.py new file mode 100644 index 0000000000..7e1773c130 --- /dev/null +++ b/website_sale_commitment_date/models/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import delivery diff --git a/website_sale_commitment_date/models/delivery.py b/website_sale_commitment_date/models/delivery.py new file mode 100644 index 0000000000..04f15b95d3 --- /dev/null +++ b/website_sale_commitment_date/models/delivery.py @@ -0,0 +1,108 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import calendar +from datetime import date, timedelta + +from babel.dates import get_month_names + +from odoo import api, fields, models + + +class DeliveryCarrier(models.Model): + _inherit = "delivery.carrier" + + allow_commitment_date = fields.Boolean( + string="Allow commitment date", + help="Allow to set a commitment date on the sale order from to the e-commerce", + ) + + min_commitment_days = fields.Float() + max_commitment_days = fields.Float() + + exclude_weekday_ids = fields.Many2many( + comodel_name="delivery.carrier.weekday", + relation="delivery_carrier_weekday_rel", + string="Exclude Weekdays", + ) + + exclude_date_ids = fields.Many2many( + comodel_name="delivery.carrier.date", + relation="delivery_carrier_date_rel", + string="Exclude Dates", + ) + + def _get_calendar_context(self, start=False): + today = fields.Date.today() + + if start: + year, month = start.year, start.month + else: + year, month = today.year, today.month + start = date(year, month, 1) + lang = self.env["res.lang"]._lang_get(self.env.lang or self.env.user.lang) + weekday_names = dict(lang.fields_get(["week_start"])["week_start"]["selection"]) + calen = calendar.Calendar(int(lang.week_start) - 1) + weeks = [] + for week in calen.monthdatescalendar(year, month): + weeks.append( + [ + { + "day": day.day, + "date": day.strftime(lang.date_format), + "is_today": day == today, + "is_disabled": self._check_calendar_disabled_day(day), + } + for day in week + ] + ) + + return { + "weekdays": [ + weekday_names[str(day + 1)][:3] for day in calen.iterweekdays() + ], + "title": "%s %s" + % (get_month_names("abbreviated", locale=lang.code)[month], year), + "month": month, + "year": year, + "start": start.strftime(lang.date_format), + "weeks": weeks, + } + + def _check_calendar_disabled_day(self, day): + if day < fields.Date.today(): + return True + if day.weekday() in self.exclude_weekday_ids.mapped("value"): + return True + if self.min_commitment_days > 0: + if day < fields.Date.today() + timedelta(days=self.min_commitment_days): + return True + if self.max_commitment_days > 0: + if day > fields.Date.today() + timedelta(days=self.max_commitment_days): + return True + if self.exclude_date_ids.filtered(lambda d: d.value == day): + return True + return False + + +class DeliveryCarrierWeekday(models.Model): + _name = "delivery.carrier.weekday" + + name = fields.Char(required=True, translate=True) + value = fields.Integer(required=True) + + +class DeliveryCarrierDate(models.Model): + _name = "delivery.carrier.date" + + name = fields.Char( + compute="_compute_name", store=True, readonly=False, string="Label" + ) + value = fields.Date(required=True, string="Date") + + @api.depends("value") + def _compute_name(self): + for record in self: + if record.value: + record.name = record.value.strftime("%d/%m/%Y") + else: + record.name = False diff --git a/website_sale_commitment_date/readme/CONTRIBUTORS.rst b/website_sale_commitment_date/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..84eb601b3b --- /dev/null +++ b/website_sale_commitment_date/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Binhex `_: + + * Adasat Torres de León diff --git a/website_sale_commitment_date/readme/DESCRIPTION.rst b/website_sale_commitment_date/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..7161d1345c --- /dev/null +++ b/website_sale_commitment_date/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This addon allows selecting the delivery date when purchasing from the e-commerce platform, +configuring excluded days of the week, minimum or maximum days to limit the selection +from the current date. All of this is configurable from the shipping method. diff --git a/website_sale_commitment_date/readme/USAGE.rst b/website_sale_commitment_date/readme/USAGE.rst new file mode 100644 index 0000000000..f6374705f6 --- /dev/null +++ b/website_sale_commitment_date/readme/USAGE.rst @@ -0,0 +1,8 @@ + +To use this addon, you need to go to the shipping method and activate the "allow commitment date" option. +Then, you can configure various settings right there. Afterward, +go to the cart in the e-commerce platform, and you will see that if you select that shipping method, +the option to choose the delivery day will appear. +When using a shipping method that requires specifying the delivery date, +the button will not appear until a date is selected. + diff --git a/website_sale_commitment_date/security/ir.model.access.csv b/website_sale_commitment_date/security/ir.model.access.csv new file mode 100644 index 0000000000..a7a4ff6a13 --- /dev/null +++ b/website_sale_commitment_date/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_delivery_carrier_weekdays,delivery.carrier.weekday,model_delivery_carrier_weekday,base.group_user,1,1,1,1 +access_delivery_carrier_dates,delivery.carrier.date,model_delivery_carrier_date,base.group_user,1,1,1,1 diff --git a/website_sale_commitment_date/static/description/icon.png b/website_sale_commitment_date/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/website_sale_commitment_date/static/description/icon.png differ diff --git a/website_sale_commitment_date/static/description/index.html b/website_sale_commitment_date/static/description/index.html new file mode 100644 index 0000000000..47e8eba0a6 --- /dev/null +++ b/website_sale_commitment_date/static/description/index.html @@ -0,0 +1,435 @@ + + + + + +Website Sale Commitment Date + + + +
+

Website Sale Commitment Date

+ + +

Beta License: AGPL-3 OCA/e-commerce Translate me on Weblate Try me on Runboat

+

This addon allows selecting the delivery date when purchasing from the e-commerce platform, +configuring excluded days of the week, minimum or maximum days to limit the selection +from the current date. All of this is configurable from the shipping method.

+

Table of contents

+ +
+

Usage

+

To use this addon, you need to go to the shipping method and activate the “allow commitment date” option. +Then, you can configure various settings right there. Afterward, +go to the cart in the e-commerce platform, and you will see that if you select that shipping method, +the option to choose the delivery day will appear. +When using a shipping method that requires specifying the delivery date, +the button will not appear until a date is selected.

+
+
+

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

+
    +
  • Binhex
  • +
+
+
+

Contributors

+ +
+
+

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.

+

This module is part of the OCA/e-commerce project on GitHub.

+

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

+
+
+
+ + diff --git a/website_sale_commitment_date/static/src/js/website_sale_delivery.js b/website_sale_commitment_date/static/src/js/website_sale_delivery.js new file mode 100644 index 0000000000..1506b3729a --- /dev/null +++ b/website_sale_commitment_date/static/src/js/website_sale_delivery.js @@ -0,0 +1,116 @@ +odoo.define("website_sale_commitment_date.checkout", function (require) { + "use strict"; + + var publicWidget = require("web.public.widget"); + var core = require("web.core"); + const QWeb = core.qweb; + var concurrency = require("web.concurrency"); + var dp = new concurrency.DropPrevious(); + + publicWidget.registry.websiteSaleDelivery = + publicWidget.registry.websiteSaleDelivery.extend({ + events: _.extend( + {}, + publicWidget.registry.websiteSaleDelivery.prototype.events, + { + "click .o_website_calendar_confirm": "_onClickCalendarConfirm", + "click .o_website_calendar_button": "_onClickCalendarButton", + "click .o_website_calendar_next": "_onClickCalendarNext", + "click .o_website_calendar_prev": "_onClickCalendarPrev", + "click .o_website_calendar_day": "_onClickCalendarDay", + } + ), + + _onClickCalendarConfirm: function (ev) { + ev.preventDefault(); + const $selected = $(".selected"); + dp.add( + this._rpc({ + route: "/shop/update_commitment_date", + params: { + date: $selected.data("date"), + }, + }) + ).then(this._handleUpdateCommitmentDate.bind(this)); + }, + + _handleUpdateCommitmentDate: function (result) { + const $payment_button = $("button[name='o_payment_submit_button']"); + const $commitment_input = $("input.o_commitment_date_input"); + if (result.success) { + $(".o_calendar_modal").modal("hide"); + $commitment_input.val(result.date); + $payment_button.show(); + } + }, + + _onClickCalendarDay: function (ev) { + ev.preventDefault(); + if ($(ev.currentTarget).data("disabled")) return; + + if ($(ev.currentTarget).hasClass("selected")) { + $(ev.currentTarget).removeClass("selected bg-primary text-white"); + return; + } + $(".selected").removeClass("selected bg-primary text-white"); + $(ev.currentTarget).addClass("selected bg-primary text-white"); + }, + + _onClickCalendarNext: function (ev) { + ev.preventDefault(); + dp.add( + this._rpc({ + route: "/calendar/commitment_date", + params: { + action: "next", + start: $(ev.currentTarget).data("start"), + }, + }) + ).then(this._handleCalendarModal.bind(this)); + }, + _onClickCalendarPrev: function (ev) { + ev.preventDefault(); + dp.add( + this._rpc({ + route: "/calendar/commitment_date", + params: { + action: "prev", + start: $(ev.currentTarget).data("start"), + }, + }) + ).then(this._handleCalendarModal.bind(this)); + }, + + _onClickCalendarButton: function (ev) { + ev.preventDefault(); + dp.add(this._rpc({route: "/calendar/commitment_date"})).then( + this._handleCalendarModal.bind(this) + ); + }, + + _handleCalendarModal: function (result) { + if (result) { + $(".o_website_calendar").html( + QWeb.render( + "website_sale_commitment_date.WebsiteCalendar", + result + ) + ); + $(".o_calendar_modal").modal("show"); + } + }, + + _handleCarrierUpdateResult: function (result) { + const $commitment_date = $("#commitment_date"); + const $payment_button = $("button[name='o_payment_submit_button']"); + if (result.allow_commitment_date) { + $commitment_date.show(); + $payment_button.hide(); + } else { + $commitment_date.hide(); + $payment_button.prop("disabled", false); + } + this._super.apply(this, arguments); + }, + }); +}); diff --git a/website_sale_commitment_date/static/src/xml/website_calendar.xml b/website_sale_commitment_date/static/src/xml/website_calendar.xml new file mode 100644 index 0000000000..6a525e820f --- /dev/null +++ b/website_sale_commitment_date/static/src/xml/website_calendar.xml @@ -0,0 +1,58 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ +
+ +
+
+
+
diff --git a/website_sale_commitment_date/tests/__init__.py b/website_sale_commitment_date/tests/__init__.py new file mode 100644 index 0000000000..b8f5c11507 --- /dev/null +++ b/website_sale_commitment_date/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import test_controllers +from . import test_delivery diff --git a/website_sale_commitment_date/tests/test_controllers.py b/website_sale_commitment_date/tests/test_controllers.py new file mode 100644 index 0000000000..4b0c0764d1 --- /dev/null +++ b/website_sale_commitment_date/tests/test_controllers.py @@ -0,0 +1,101 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from datetime import date + +from freezegun import freeze_time + +from odoo.tests import tagged +from odoo.tests.common import HttpCase + +from odoo.addons.website.tools import MockRequest +from odoo.addons.website_sale_commitment_date.controllers.main import ( + WebsiteSaleCommitmentDate, +) + + +@freeze_time("2025-01-09 15:00:00") +@tagged("post_install", "-at_install") +class TestWebsiteSaleCommitmentDateController(HttpCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.website = cls.env.ref("website.default_website") + cls.Controller = WebsiteSaleCommitmentDate() + cls.DeliveryCarrier = cls.env["delivery.carrier"] + cls.lang = cls.env["res.lang"]._lang_get(cls.env.user.lang) + + def test01_website_sale_commitment_date(self): + with MockRequest(self.env, website=self.website): + order = self.website.sale_get_order(force_create=True) + carrier_id = self.DeliveryCarrier.create( + { + "name": "Test carrier Allow commitment date", + "allow_commitment_date": True, + "product_id": self.env.ref("product.product_product_4").id, + } + ) + order.carrier_id = carrier_id.id + response = self.Controller.commitment_date() + self.assertEqual(response["month"], 1) + self.assertEqual(response["year"], 2025) + self.assertTrue(response["weeks"]) + self.assertEqual( + response["start"], date(2025, 1, 1).strftime(self.lang.date_format) + ) + response = self.Controller.commitment_date( + **{"action": "next", "start": response["start"]} + ) + self.assertEqual(response["month"], 2) + self.assertEqual(response["year"], 2025) + self.assertEqual( + response["start"], date(2025, 2, 1).strftime(self.lang.date_format) + ) + response = self.Controller.commitment_date( + **{"action": "next", "start": response["start"]} + ) + self.assertEqual(response["month"], 3) + self.assertEqual(response["year"], 2025) + self.assertEqual( + response["start"], date(2025, 3, 1).strftime(self.lang.date_format) + ) + response = self.Controller.commitment_date( + **{"action": "prev", "start": response["start"]} + ) + self.assertEqual(response["month"], 2) + self.assertEqual(response["year"], 2025) + self.assertEqual( + response["start"], date(2025, 2, 1).strftime(self.lang.date_format) + ) + response = self.Controller.commitment_date( + **{"action": "prev", "start": response["start"]} + ) + self.assertEqual(response["month"], 1) + self.assertEqual(response["year"], 2025) + self.assertEqual( + response["start"], + date(2025, 1, 1).strftime(self.lang.date_format), + ) + + def test02_website_update_commitment_date(self): + with MockRequest(self.env, website=self.website): + order = self.website.sale_get_order(force_create=True) + order.carrier_id = self.DeliveryCarrier.create( + { + "name": "Test carrier Allow commitment date", + "allow_commitment_date": True, + "product_id": self.env.ref("product.product_product_4").id, + } + ).id + response = self.Controller.update_commitment_date( + **{"date": date(2025, 1, 10).strftime(self.lang.date_format)} + ) + self.assertTrue(response["success"]) + self.assertEqual( + response["date"], date(2025, 1, 10).strftime(self.lang.date_format) + ) + self.assertEqual( + order.commitment_date.strftime(self.lang.date_format), + date(2025, 1, 10).strftime(self.lang.date_format), + ) diff --git a/website_sale_commitment_date/tests/test_delivery.py b/website_sale_commitment_date/tests/test_delivery.py new file mode 100644 index 0000000000..efcd30491f --- /dev/null +++ b/website_sale_commitment_date/tests/test_delivery.py @@ -0,0 +1,64 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from datetime import date + +from freezegun import freeze_time + +from odoo.tests import tagged +from odoo.tests.common import TransactionCase + + +@freeze_time("2025-01-09 15:00:00") +@tagged("post_install", "-at_install") +class TestDeliveryCarrier(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.DeliveryCarrier = cls.env["delivery.carrier"] + + def test01_delivery_carrier(self): + carrier = self.DeliveryCarrier.create( + { + "name": "Test carrier", + "product_id": self.env.ref("product.product_product_4").id, + "allow_commitment_date": True, + "min_commitment_days": 2, + "max_commitment_days": 15, + } + ) + self.assertTrue(carrier.allow_commitment_date) + self.assertEqual(carrier.min_commitment_days, 2) + self.assertEqual(carrier.max_commitment_days, 15) + self.assertFalse(carrier.exclude_weekday_ids) + + carrier.write({"exclude_weekday_ids": [(6, 0, [1, 2])]}) + + self.assertEqual(len(carrier.exclude_weekday_ids), 2) + self.assertIn(1, carrier.exclude_weekday_ids.ids) + self.assertIn(2, carrier.exclude_weekday_ids.ids) + + res = carrier._get_calendar_context() + self.assertTrue(res) + self.assertIn("month", res) + self.assertIn("year", res) + self.assertEqual(res["month"], 1) + self.assertEqual(res["year"], 2025) + + res = carrier._get_calendar_context(start=date(2026, 2, 1)) + self.assertTrue(res) + self.assertIn("month", res) + self.assertIn("year", res) + self.assertEqual(res["month"], 2) + self.assertEqual(res["year"], 2026) + + res = carrier._check_calendar_disabled_day(date(2025, 1, 1)) + self.assertTrue(res) + res = carrier._check_calendar_disabled_day(date(2025, 1, 9)) + self.assertTrue(res) + res = carrier._check_calendar_disabled_day(date(2025, 1, 28)) + self.assertTrue(res) + res = carrier._check_calendar_disabled_day(date(2025, 1, 13)) + self.assertTrue(res) + res = carrier._check_calendar_disabled_day(date(2025, 1, 23)) + self.assertFalse(res) diff --git a/website_sale_commitment_date/views/delivery_carrier_templates.xml b/website_sale_commitment_date/views/delivery_carrier_templates.xml new file mode 100644 index 0000000000..0d8e83bee2 --- /dev/null +++ b/website_sale_commitment_date/views/delivery_carrier_templates.xml @@ -0,0 +1,77 @@ + + + + + diff --git a/website_sale_commitment_date/views/delivery_carrier_views.xml b/website_sale_commitment_date/views/delivery_carrier_views.xml new file mode 100644 index 0000000000..21e8795070 --- /dev/null +++ b/website_sale_commitment_date/views/delivery_carrier_views.xml @@ -0,0 +1,61 @@ + + + + delivery.carrier.date.view.tree + delivery.carrier.date + + + + + + + + + Exclude Dates + delivery.carrier.date + tree + + + delivery.carrier.view.form.inherit + delivery.carrier + + + + + + + + + + + + + + +