From 59184cdfdd6e8a5f5947347f3d2fb5125bce0bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 31 Oct 2025 11:57:19 +0100 Subject: [PATCH] Add a default Incoterm to web shops The default Incoterm is set by default to sale from web shop for which it is required. And the shipment address is also set by default as Incoterm location when it is required. Closes #14337 --- modules/incoterm/CHANGELOG | 1 + modules/incoterm/sale.py | 27 ++++++++++++++++++++- modules/incoterm/setup.py | 1 + modules/incoterm/tests/test_module.py | 2 +- modules/incoterm/tryton.cfg | 7 ++++++ modules/incoterm/view/web_shop_form.xml | 10 ++++++++ modules/incoterm/web.py | 32 +++++++++++++++++++++++++ modules/incoterm/web.xml | 12 ++++++++++ 8 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 modules/incoterm/view/web_shop_form.xml create mode 100644 modules/incoterm/web.py create mode 100644 modules/incoterm/web.xml diff --git a/modules/incoterm/CHANGELOG b/modules/incoterm/CHANGELOG index f5a22d9323..cf843a0f70 100644 --- a/modules/incoterm/CHANGELOG +++ b/modules/incoterm/CHANGELOG @@ -1,3 +1,4 @@ +* Add a default Incoterm to web shops * Allow modifications of incoterm until customer's shipments has been shipped Version 7.6.0 - 2025-04-28 diff --git a/modules/incoterm/sale.py b/modules/incoterm/sale.py index 2bd03d44f8..780740fe75 100644 --- a/modules/incoterm/sale.py +++ b/modules/incoterm/sale.py @@ -2,7 +2,7 @@ # this repository contains the full copyright notices and license terms. from trytond.i18n import gettext -from trytond.model import fields +from trytond.model import ModelView, Workflow, fields from trytond.pool import Pool, PoolMeta from trytond.pyson import Eval @@ -105,6 +105,31 @@ class Sale_Carrier(metaclass=PoolMeta): self._set_default_incoterm() +class Sale_WebShop(metaclass=PoolMeta): + __name__ = 'sale.sale' + + @property + @fields.depends('web_shop') + def _party_incoterms(self): + incoterms = super()._party_incoterms + if self.web_shop: + incoterms = [] + return incoterms + + @classmethod + @ModelView.button + @Workflow.transition('quotation') + def quote(cls, sales): + for sale in sales: + if sale.web_shop and sale._incoterm_required: + if not sale.incoterm: + sale.incoterm = sale.web_shop.default_incoterm + if sale.incoterm and sale.incoterm.location: + sale.incoterm_location = sale.shipment_address + cls.save(sales) + super().quote(sales) + + class Opportunity(IncotermMixin, metaclass=PoolMeta): __name__ = 'sale.opportunity' diff --git a/modules/incoterm/setup.py b/modules/incoterm/setup.py index d5459bcca4..19d1b81156 100755 --- a/modules/incoterm/setup.py +++ b/modules/incoterm/setup.py @@ -63,6 +63,7 @@ tests_require = [ get_require_version('trytond_sale_opportunity'), get_require_version('trytond_sale_shipment_grouping'), get_require_version('trytond_stock'), + get_require_version('trytond_web_shop'), ] setup(name=name, diff --git a/modules/incoterm/tests/test_module.py b/modules/incoterm/tests/test_module.py index a345f83746..c80e896ffb 100644 --- a/modules/incoterm/tests/test_module.py +++ b/modules/incoterm/tests/test_module.py @@ -15,7 +15,7 @@ class IncotermTestCase(CompanyTestMixin, ModuleTestCase): 'carrier', 'company', 'purchase', 'purchase_request_quotation', 'sale', 'sale_shipment_cost', 'sale_opportunity', 'sale_shipment_grouping', 'stock', 'account_invoice', - 'account_invoice_stock'] + 'account_invoice_stock', 'web_shop'] @with_transaction() def test_shipment_grouping(self): diff --git a/modules/incoterm/tryton.cfg b/modules/incoterm/tryton.cfg index 0524dc8ff2..26d5157962 100644 --- a/modules/incoterm/tryton.cfg +++ b/modules/incoterm/tryton.cfg @@ -17,6 +17,7 @@ extras_depend: sale_shipment_grouping stock stock_package_shipping + web_shop xml: incoterm.xml company.xml @@ -25,6 +26,7 @@ xml: purchase.xml sale.xml stock.xml + web.xml message.xml [register] @@ -75,3 +77,8 @@ model: stock.ShipmentInReturn stock.ShipmentOut stock.ShipmentOutReturn + +[register web_shop] +model: + sale.Sale_WebShop + web.Shop diff --git a/modules/incoterm/view/web_shop_form.xml b/modules/incoterm/view/web_shop_form.xml new file mode 100644 index 0000000000..656d03b9fc --- /dev/null +++ b/modules/incoterm/view/web_shop_form.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/modules/incoterm/web.py b/modules/incoterm/web.py new file mode 100644 index 0000000000..86c14cc731 --- /dev/null +++ b/modules/incoterm/web.py @@ -0,0 +1,32 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. + +from trytond.model import fields +from trytond.pool import Pool, PoolMeta +from trytond.pyson import Eval + + +class Shop(metaclass=PoolMeta): + __name__ = 'web.shop' + + default_incoterm = fields.Many2One( + 'incoterm.incoterm', "Default Incoterm", + domain=[ + ('carrier', '=', 'seller'), + ('id', 'in', Eval('available_incoterms', [])), + ], + help="Used to fill incoterm on sales that require it.") + available_incoterms = fields.Function(fields.Many2Many( + 'incoterm.incoterm', None, None, "Available Incoterms"), + 'on_change_with_available_incoterms') + + @fields.depends('company', methods=['_get_incoterm_pattern']) + def on_change_with_available_incoterms(self, name=None): + pool = Pool() + Incoterm = pool.get('incoterm.incoterm') + pattern = self._get_incoterm_pattern() + return Incoterm.get_incoterms(self.company, pattern) + + @fields.depends() + def _get_incoterm_pattern(self): + return {} diff --git a/modules/incoterm/web.xml b/modules/incoterm/web.xml new file mode 100644 index 0000000000..dd97840ecf --- /dev/null +++ b/modules/incoterm/web.xml @@ -0,0 +1,12 @@ + + + + + + web.shop + + web_shop_form + + +