Skip to content

Commit

Permalink
[ADD]sale_order_country_allowed_product: Restrict products by country…
Browse files Browse the repository at this point in the history
… in sales
  • Loading branch information
manuelregidor committed Feb 28, 2025
1 parent 1593a90 commit e1464e9
Show file tree
Hide file tree
Showing 21 changed files with 878 additions and 0 deletions.
96 changes: 96 additions & 0 deletions sale_order_country_allowed_product/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
==================================
Sale Order Country Allowed Product
==================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f665862cdb5cce2361a0deb273c056187ed7d7083c49f373cc7af4c7d4e4c1fc
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fsale--workflow-lightgray.png?logo=github
:target: https://github.com/OCA/sale-workflow/tree/16.0/sale_order_country_allowed_product
:alt: OCA/sale-workflow
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/sale-workflow-16-0/sale-workflow-16-0-sale_order_country_allowed_product
: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/sale-workflow&target_branch=16.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows to restrict the selection of products in sale order lines based on the shipping address country.

**Table of contents**

.. contents::
:local:

Configuration
=============

To select the countries in which a product is available you need to:

- Go to a product template form view.
- Select the countries in which the product is available in field "Sale Allowed Countries".

Users in group "Ignore products sale countries" will gain access to all salable products in sale orders, even to those that are not available in the shipping addres country.

Usage
=====

Users in "Ignore products sale countries" group will be able to select all the salable products in sale order lines, even those that are not available in the country of the shipping address. Users who do not belong to that group, will only be able to select the products available in the country of the shipping address. Products with the "Sale Allowed Countries" field empty are considered to be available in all countries.

A message on the top of the sale order will be displayed if the sale order contains unavailable products.

Users who do not belong to the "Ignore products sale countries" group will be unable to confirm sale orders containing unavailable products.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-workflow/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_order_country_allowed_product%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
~~~~~~~

* Sygel

Contributors
~~~~~~~~~~~~

* Manuel Regidor <manuel.regidor@sygel.es>
* Valentín Vinagre <valentin.vinagre@sygel.es>

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/sale-workflow <https://github.com/OCA/sale-workflow/tree/16.0/sale_order_country_allowed_product>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 4 additions & 0 deletions sale_order_country_allowed_product/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import models
22 changes: 22 additions & 0 deletions sale_order_country_allowed_product/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Sale Order Country Allowed Product",
"summary": "Restrict products in sales by country",
"version": "16.0.1.0.0",
"category": "Sales",
"website": "https://github.com/OCA/sale-workflow",
"author": "Sygel, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"sale",
],
"data": [
"security/res_groups.xml",
"views/sale_order_views.xml",
"views/product_views.xml",
],
}
7 changes: 7 additions & 0 deletions sale_order_country_allowed_product/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import product_product
from . import product_template
from . import sale_order
from . import sale_order_line
46 changes: 46 additions & 0 deletions sale_order_country_allowed_product/models/product_product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, models


class ProductProduct(models.Model):
_inherit = "product.product"

@api.model
def _search(
self,
args,
offset=0,
limit=None,
order=None,
count=False,
access_rights_uid=None,
):
if self.env.context.get(
"restrict_by_country", False
) and not self.env.user.has_group(
"sale_order_country_allowed_product.ignore_country_sale"
):
partner = self.env["res.partner"].search(
[("id", "=", self.env.context.get("restrict_by_country_partner_id"))],
limit=1,
)
if partner.country_id:
args += [
"|",
("product_tmpl_id.sale_allowed_country_ids", "=", False),
(
"product_tmpl_id.sale_allowed_country_ids",
"in",
[partner.country_id.id],
),
]
return super()._search(
args,
offset=offset,
limit=limit,
order=order,
count=count,
access_rights_uid=access_rights_uid,
)
12 changes: 12 additions & 0 deletions sale_order_country_allowed_product/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ProductTemplate(models.Model):
_inherit = "product.template"

sale_allowed_country_ids = fields.Many2many(
comodel_name="res.country", string="Sale Allowed Countries"
)
44 changes: 44 additions & 0 deletions sale_order_country_allowed_product/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError


class SaleOrder(models.Model):
_inherit = "sale.order"

unavailable_product_msg = fields.Html(compute="_compute_unavailable_product_msg")

@api.depends("order_line.product_id")
def _compute_unavailable_product_msg(self):
for order in self:
unavailable_product_msg = ""
if any(not line.country_available for line in order.order_line):
products = order.order_line.filtered(
lambda line: not line.country_available
).mapped("product_id")
if products:
products_list = (
f'<ul>{"".join(f"<li>{p.name}</li>" for p in products)}</ul>'
)
unavailable_product_msg = _(
"The following products are not available in the shipping country: "
"%(products_list)s"
) % {"products_list": products_list}

order.unavailable_product_msg = unavailable_product_msg

def action_confirm(self):
if any(
not line.country_available for line in self.order_line
) and not self.env.user.has_group(
"sale_order_country_allowed_product.ignore_country_sale"
):
raise ValidationError(
_(
"Sale order cannot be validated as some products are not available "
"in the shipping country."
)
)
return super().action_confirm()
20 changes: 20 additions & 0 deletions sale_order_country_allowed_product/models/sale_order_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2025 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import api, fields, models


class SaleOrderLine(models.Model):
_inherit = "sale.order.line"

country_available = fields.Boolean(compute="_compute_country_available")

@api.depends("product_id", "order_id.partner_shipping_id")
def _compute_country_available(self):
for line in self:
allowed_countries = line.product_id.sale_allowed_country_ids
line.country_available = (
not allowed_countries
or line.order_id.partner_shipping_id.country_id.id
in allowed_countries.ids
)
6 changes: 6 additions & 0 deletions sale_order_country_allowed_product/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
To select the countries in which a product is available you need to:

- Go to a product template form view.
- Select the countries in which the product is available in field "Sale Allowed Countries".

Users in group "Ignore products sale countries" will gain access to all salable products in sale orders, even to those that are not available in the shipping addres country.
2 changes: 2 additions & 0 deletions sale_order_country_allowed_product/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Manuel Regidor <manuel.regidor@sygel.es>
* Valentín Vinagre <valentin.vinagre@sygel.es>
1 change: 1 addition & 0 deletions sale_order_country_allowed_product/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This module allows to restrict the selection of products in sale order lines based on the shipping address country.
5 changes: 5 additions & 0 deletions sale_order_country_allowed_product/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Users in "Ignore products sale countries" group will be able to select all the salable products in sale order lines, even those that are not available in the country of the shipping address. Users who do not belong to that group, will only be able to select the products available in the country of the shipping address. Products with the "Sale Allowed Countries" field empty are considered to be available in all countries.

A message on the top of the sale order will be displayed if the sale order contains unavailable products.

Users who do not belong to the "Ignore products sale countries" group will be unable to confirm sale orders containing unavailable products.
6 changes: 6 additions & 0 deletions sale_order_country_allowed_product/security/res_groups.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="ignore_country_sale" model="res.groups">
<field name="name">Ignore products sale countries</field>
</record>
</odoo>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e1464e9

Please sign in to comment.