diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cf5b7681..5a302bde 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,7 @@ jobs: container: ${{ matrix.container }} name: ${{ matrix.name }} env: + ADDONS_PATH: ${{ matrix.addons_path }} EXCLUDE: ${{ matrix.exclude }} strategy: fail-fast: false @@ -39,10 +40,16 @@ jobs: include: - container: ghcr.io/oca/oca-ci/py3.10-odoo17.0:latest name: test with Odoo - exclude: tg_website_event_sale_commission + exclude: tg_website_event_sale_commission,tg_website_sale_renting + addons_path: /opt/odoo/addons - container: ghcr.io/oca/oca-ci/py3.10-odoo17.0:latest name: test with Odoo (no compat test) - exclude: test_compat_tg_addons,tg_website_event_sale_commission + exclude: test_compat_tg_addons,tg_website_event_sale_commission,tg_website_sale_renting + addons_path: /opt/odoo/addons + - container: ghcr.io/oca/oca-ci/py3.10-odoo17.0:latest + name: test with Odoo Enterprise + exclude: tg_website_event_sale_commission + addons_path: /opt/odoo/addons,./enterprise services: postgres: image: postgres:12.0 @@ -56,10 +63,25 @@ jobs: - uses: actions/checkout@v3 with: persist-credentials: false + - name: Clone enterprise + if: contains(matrix.addons_path, 'enterprise') + uses: actions/checkout@v3 + with: + repository: em230418/enterprise + path: enterprise + ref: "17.0" + token: ${{ secrets.ENTERPRISE_REPO_TOKEN }} + fetch-depth: 1 + - name: fix oca_list_external_dependencies + if: false == contains(matrix.addons_path, 'enterprise') + run: | + rm /usr/local/bin/oca_list_external_dependencies + curl https://raw.githubusercontent.com/em230418/oca-ci/refs/heads/patch-1/bin/oca_list_external_dependencies > /usr/local/bin/oca_list_external_dependencies + chmod +x /usr/local/bin/oca_list_external_dependencies - name: Install addons and dependencies run: oca_install_addons - name: Check licenses - run: manifestoo -d . check-licenses + run: manifestoo -d . --select-exclude ${{ matrix.exclude}} check-licenses - name: Check development status run: manifestoo -d . check-dev-status --default-dev-status=Beta continue-on-error: true diff --git a/tg_website_sale_renting/README.rst b/tg_website_sale_renting/README.rst new file mode 100644 index 00000000..4c57ac5c --- /dev/null +++ b/tg_website_sale_renting/README.rst @@ -0,0 +1,53 @@ +===================================================== + eCommerce Rental modifications for Tribal Gathering +===================================================== + +Rental dates defaults +--------------------- + +- Settings -> Rental -> Rent online + +- Set following fields: + + * Renting Default Start Date + + * Renting Default End Date + + * Renting Min Start Date + + * Renting Max End Date + +Usage +----- + +After settings fields above: + +- Navigate to shop (/shop) + +- Choose existing renting product + +- RESULT: default dates are set from config + +- Choose other date range + +- RESULT: minimal start date is set from config + +- RESULT: maximal end date is set from config + +Credits +======= + +Contributors +------------ + +* `Eugene Molotov `__ + +Sponsors +-------- + +* `Tribal Gathering `__ + +Maintainers +----------- + +* `IT-Projects LLC `__ diff --git a/tg_website_sale_renting/__init__.py b/tg_website_sale_renting/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/tg_website_sale_renting/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/tg_website_sale_renting/__manifest__.py b/tg_website_sale_renting/__manifest__.py new file mode 100644 index 00000000..b9b8f486 --- /dev/null +++ b/tg_website_sale_renting/__manifest__.py @@ -0,0 +1,21 @@ +{ + "name": """eCommerce Rental modifications for Tribal Gathering""", + "version": "17.0.0.1.0", + "author": "IT-Projects LLC, Eugene Molotov", + "support": "it@it-projects.info", + "website": "https://github.com/it-projects-llc/tg-addons", + "license": "LGPL-3", + "depends": [ + "website_sale_renting", + ], + "assets": { + "web.assets_frontend": [ + "tg_website_sale_renting/static/src/js/*.js", + ], + }, + "data": [ + "views/templates.xml", + "views/res_config_settings_views.xml", + ], + "demo": [], +} diff --git a/tg_website_sale_renting/models/__init__.py b/tg_website_sale_renting/models/__init__.py new file mode 100644 index 00000000..9797edf9 --- /dev/null +++ b/tg_website_sale_renting/models/__init__.py @@ -0,0 +1,3 @@ +from . import product_template +from . import res_config_settings +from . import res_company diff --git a/tg_website_sale_renting/models/product_template.py b/tg_website_sale_renting/models/product_template.py new file mode 100644 index 00000000..820b7942 --- /dev/null +++ b/tg_website_sale_renting/models/product_template.py @@ -0,0 +1,27 @@ +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + @api.model + def _get_default_start_date(self, *args, **kw): + company = self.company_id or self.env.company + return fields.Datetime.to_datetime( + company.renting_default_start_date + ) or super()._get_default_start_date(*args, **kw) + + @api.model + def _get_default_end_date(self, *args, **kw): + company = self.company_id or self.env.company + return fields.Datetime.to_datetime( + company.renting_default_end_date + ) or super()._get_default_end_date(*args, **kw) + + def _get_renting_min_start_date(self): + company = self.company_id or self.env.company + return fields.Datetime.to_datetime(company.renting_min_start_date) + + def _get_renting_max_end_date(self): + company = self.company_id or self.env.company + return fields.Datetime.to_datetime(company.renting_max_end_date) diff --git a/tg_website_sale_renting/models/res_company.py b/tg_website_sale_renting/models/res_company.py new file mode 100644 index 00000000..7b88f596 --- /dev/null +++ b/tg_website_sale_renting/models/res_company.py @@ -0,0 +1,100 @@ +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools.misc import format_date + + +class Company(models.Model): + _inherit = "res.company" + + renting_default_start_date = fields.Date() + renting_default_end_date = fields.Date() + renting_min_start_date = fields.Date() + renting_max_end_date = fields.Date() + + @api.constrains( + "renting_min_start_date", + "renting_max_end_date", + ) + def _check_renting_dates_and_ranges1(self): + def f(v): + return format_date(self.env, v) + + for c in self: + if ( + c.renting_min_start_date + and c.renting_max_end_date + and c.renting_min_start_date > c.renting_max_end_date + ): + raise ValidationError( + _( + "Renting minimal start date (%(min_start_date)s) cannot be greater than maximal end date (%(max_end_date)s)", # noqa: E501 + min_start_date=f(c.renting_min_start_date), + max_end_date=f(c.renting_max_end_date), + ) + ) + + @api.constrains( + "renting_default_start_date", + "renting_default_end_date", + ) + def _check_renting_dates_and_ranges2(self): + def f(v): + return format_date(self.env, v) + + for c in self: + if ( + c.renting_default_start_date + and c.renting_default_end_date + and c.renting_default_start_date > c.renting_default_end_date + ): + raise ValidationError( + _( + "Default renting start date (%(default_start_date)s) cannot be greater default renting end date (%(default_end_date)s)", # noqa: E501 + default_start_date=f(c.renting_default_start_date), + default_end_date=f(c.renting_default_end_date), + ) + ) + + @api.constrains( + "renting_default_start_date", + "renting_min_start_date", + ) + def _check_renting_dates_and_ranges3(self): + def f(v): + return format_date(self.env, v) + + for c in self: + if ( + c.renting_min_start_date + and c.renting_default_start_date + and c.renting_default_start_date < c.renting_min_start_date + ): + raise ValidationError( + _( + "Renting default start date (%(default_start_date)s) cannot be less than minimal start date (%(min_start_date)s)", # noqa: E501 + default_start_date=f(c.renting_default_start_date), + min_start_date=f(c.renting_min_start_date), + ) + ) + + @api.constrains( + "renting_default_end_date", + "renting_max_end_date", + ) + def _check_renting_dates_and_ranges4(self): + def f(v): + return format_date(self.env, v) + + for c in self: + if ( + c.renting_max_end_date + and c.renting_default_end_date + and c.renting_default_end_date > c.renting_max_end_date + ): + raise ValidationError( + _( + "Renting default end date (%(default_end_date)s) cannot be greater than maximal end date (%(max_end_date)s)", # noqa: E501 + default_end_date=f(c.renting_default_end_date), + max_end_date=f(c.renting_max_end_date), + ) + ) diff --git a/tg_website_sale_renting/models/res_config_settings.py b/tg_website_sale_renting/models/res_config_settings.py new file mode 100644 index 00000000..79817149 --- /dev/null +++ b/tg_website_sale_renting/models/res_config_settings.py @@ -0,0 +1,21 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + renting_default_start_date = fields.Date( + related="company_id.renting_default_start_date", readonly=False + ) + + renting_default_end_date = fields.Date( + related="company_id.renting_default_end_date", readonly=False + ) + + renting_min_start_date = fields.Date( + related="company_id.renting_min_start_date", readonly=False + ) + + renting_max_end_date = fields.Date( + related="company_id.renting_max_end_date", readonly=False + ) diff --git a/tg_website_sale_renting/pyproject.toml b/tg_website_sale_renting/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/tg_website_sale_renting/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/tg_website_sale_renting/static/src/js/website_sale_renting_daterangepicker.js b/tg_website_sale_renting/static/src/js/website_sale_renting_daterangepicker.js new file mode 100644 index 00000000..e3d641a0 --- /dev/null +++ b/tg_website_sale_renting/static/src/js/website_sale_renting_daterangepicker.js @@ -0,0 +1,61 @@ +/** @odoo-module **/ + +import WebsiteSaleDaterangePicker from "@website_sale_renting/js/website_sale_renting_daterangepicker"; +const {DateTime} = luxon; + +WebsiteSaleDaterangePicker.include({ + _initSaleRentingDateRangePicker(el) { + const hasDefaultDates = Boolean(this._hasDefaultDates()); + el.dataset.hasDefaultDates = hasDefaultDates; + // <-- changes start + const minStartDate = DateTime.fromSQL(el.dataset.minStartDate); + const maxEndDate = DateTime.fromSQL(el.dataset.maxEndDate); + // <-- changes end; + const value = + this.isShopDatePicker && !hasDefaultDates + ? ["", ""] + : [this.startDate, this.endDate]; + this.call( + "datetime_picker", + "create", + { + target: el, + pickerProps: { + value, + range: true, + type: this._isDurationWithHours() ? "datetime" : "date", + minDate: minStartDate.isValid + ? minStartDate + : DateTime.min(DateTime.now(), this.startDate), + maxDate: maxEndDate.isValid + ? maxEndDate + : DateTime.max(DateTime.now().plus({years: 3}), this.endDate), + isDateValid: this._isValidDate.bind(this), + dayCellClass: (date) => this._isCustomDate(date).join(" "), + }, + onApply: ([start_date, end_date]) => { + this.startDate = start_date; + this.endDate = end_date; + this._verifyValidPeriod(); + this.$("input[name=renting_start_date]").change(); + this.$el.trigger("daterangepicker_apply", { + start_date, + end_date, + }); + }, + }, + () => [ + el.querySelector("input[name=renting_start_date]"), + el.querySelector("input[name=renting_end_date]"), + ] + ).enable(); + + // Removing the pointer event here to avoid updating templates in stable. + const inputElement = el.querySelector("input[name=renting_start_date]"); + if (inputElement?.disabled) { + inputElement.parentElement + .querySelector("div .input-group-text.cursor-pointer") + ?.classList.add("pe-none"); + } + }, +}); diff --git a/tg_website_sale_renting/views/res_config_settings_views.xml b/tg_website_sale_renting/views/res_config_settings_views.xml new file mode 100644 index 00000000..47653be2 --- /dev/null +++ b/tg_website_sale_renting/views/res_config_settings_views.xml @@ -0,0 +1,32 @@ + + + + res.config.settings.view.form.inherit.tg.website.sale.renting + res.config.settings + + + + + + + + + + + + + + + + + + + diff --git a/tg_website_sale_renting/views/templates.xml b/tg_website_sale_renting/views/templates.xml new file mode 100644 index 00000000..8346101d --- /dev/null +++ b/tg_website_sale_renting/views/templates.xml @@ -0,0 +1,13 @@ + + + +