Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions product_unique_internal_reference/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
=================================
Product unique internal reference
=================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:976812157684886bd583c3621ad271c233ae90a365cbb84fa272c9c9fc0f9075
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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-NuoBiT%2Fodoo--addons-lightgray.png?logo=github
:target: https://github.com/NuoBiT/odoo-addons/tree/18.0/product_unique_internal_reference
:alt: NuoBiT/odoo-addons

|badge1| |badge2| |badge3|

- This module ensures that you enter a 'Unique' Internal Reference
(default_code) for your Products.
- Multi company aware

**Table of contents**

.. contents::
:local:

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

Bugs are tracked on `GitHub Issues <https://github.com/NuoBiT/odoo-addons/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/NuoBiT/odoo-addons/issues/new?body=module:%20product_unique_internal_reference%0Aversion:%2018.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
-------

* NuoBiT Solutions SL

Contributors
------------

- `NuoBiT <https://www.nuobit.com>`__:

- Eric Antones eantones@nuobit.com
- Bijaya Kumal bkumal@nuobit.com
- Deniz Gallo dgallo@nuobit.com

Maintainers
-----------

This module is part of the `NuoBiT/odoo-addons <https://github.com/NuoBiT/odoo-addons/tree/18.0/product_unique_internal_reference>`_ project on GitHub.

You are welcome to contribute.
2 changes: 2 additions & 0 deletions product_unique_internal_reference/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from .hooks import internal_reference_duplicate_check
19 changes: 19 additions & 0 deletions product_unique_internal_reference/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright NuoBiT - Eric Antones <eantones@nuobit.com>
# Copyright NuoBiT 2025 - Bijaya Kumal <bkumal@nuobit.com>
# Copyright NuoBiT 2025 - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

{
"name": "Product unique internal reference",
"summary": "This module ensures that you enter a "
"Unique Internal Reference (default_code) for your Products",
"version": "18.0.1.0.0",
"category": "Sales",
"author": "NuoBiT Solutions SL",
"website": "https://github.com/NuoBiT/odoo-addons",
"license": "AGPL-3",
"depends": [
"product",
],
"pre_init_hook": "internal_reference_duplicate_check",
}
36 changes: 36 additions & 0 deletions product_unique_internal_reference/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright NuoBiT - Eric Antones <eantones@nuobit.com>
# Copyright NuoBiT 2025 - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)


from odoo import _
from odoo.exceptions import ValidationError


def internal_reference_duplicate_check(env):
"""This hook will look to see if any conflicting internal references exist before
the module is installed
:param Odoo env: Odoo environment
"""
with env.cr.savepoint():
env.cr.execute(
"""
SELECT p0.id, p0.default_code, t0.company_id
FROM product_product p0, product_template t0
WHERE p0.product_tmpl_id = t0.id AND
EXISTS (
SELECT 1
FROM product_product p1, product_template t1
WHERE p1.product_tmpl_id = t1.id AND
(t1.company_id is null OR t0.company_id is null OR
t1.company_id = t0.company_id) AND
p1.default_code = p0.default_code AND p1.id != p0.id
)"""
)
products = sorted(["[%i] %s (%i)" % p for p in env.cr.fetchall()])
if products:
raise ValidationError(
_("Conflicting internal references exist: {}").format(
", ".join(products)
)
)
122 changes: 122 additions & 0 deletions product_unique_internal_reference/i18n/es.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_unique_internal_reference
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-12-16 14:21+0000\n"
"PO-Revision-Date: 2021-12-16 14:21+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: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/hooks.py:0
#, python-format
msgid "Conflicting internal references exist: %s, "
msgstr "Existe un conflicto de referencias internas: %s, "

#. module: product_unique_internal_reference
#: model:ir.model.fields,field_description:product_unique_internal_reference.field_product_product__display_name
#: model:ir.model.fields,field_description:product_unique_internal_reference.field_product_template__display_name
msgid "Display Name"
msgstr "Nombre mostrado"

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/models/product_product.py:0
#, python-format
msgid ""
"Error! The Default Code %s already exists. Check also the archived ones."
msgstr ""
"Error! La referencia interna %s ya existe. Comprobar también los productos "
"archivados."

#. module: product_unique_internal_reference
#: model:ir.model.fields,field_description:product_unique_internal_reference.field_product_product__id
#: model:ir.model.fields,field_description:product_unique_internal_reference.field_product_template__id
msgid "ID"
msgstr ""

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#, python-format
msgid ""
"It has been possible to change the template Internal Reference existing a "
"variant with the same one"
msgstr ""
"Ha sido posible cambiar la referencia interna de la plantilla existiendo una "
"variante con la misma"

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#, python-format
msgid ""
"It has been possible to create a product template on one company and another"
" without company with the same Internal Reference"
msgstr ""
"Ha sido posible crear una plantilla de producto en una compañía y otra sin "
"compañía con la misma referencia interna"

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#, python-format
msgid ""
"It has been possible to create a product template when a variant of another "
"template has the same Internal Reference"
msgstr ""
"Ha sido posible crear una plantilla de producto cuando una variante de otra "
"plantilla tiene la misma referencia interna"

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#, python-format
msgid ""
"It has been possible to create a product variant when a variant of another "
"template has the same Internal Reference"
msgstr ""
"Ha sido posible crear una variante de producto cuando una variante de otra "
"plantilla tiene la misma referencia interna"

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#, python-format
msgid ""
"It has been possible to create two product templates with the same Internal "
"Reference"
msgstr ""
"Ha sido posible crear dos plantillas de producto con la misma referencia "
"interna"

#. module: product_unique_internal_reference
#: model:ir.model.fields,field_description:product_unique_internal_reference.field_product_product____last_update
#: model:ir.model.fields,field_description:product_unique_internal_reference.field_product_template____last_update
msgid "Last Modified on"
msgstr "Última modificación el"

#. module: product_unique_internal_reference
#: model:ir.model,name:product_unique_internal_reference.model_product_product
msgid "Product"
msgstr "Producto"

#. module: product_unique_internal_reference
#: model:ir.model,name:product_unique_internal_reference.model_product_template
msgid "Product Template"
msgstr "Plantilla de producto"

#. module: product_unique_internal_reference
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#: code:addons/product_unique_internal_reference/tests/test_product_unique_internal_reference.py:0
#, python-format
msgid ""
"The Internal References are not equal, this should have not raised an "
"Exception"
msgstr ""
"Las referencias internas no son iguales, esto no debería haber lanzado una "
"excepción"
Copy link

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .po file is missing a blank line at the end of the file, which is required by coding guidelines.

Copilot uses AI. Check for mistakes.
2 changes: 2 additions & 0 deletions product_unique_internal_reference/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import product_product
from . import product_template
46 changes: 46 additions & 0 deletions product_unique_internal_reference/models/product_product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright NuoBiT - Eric Antones <eantones@nuobit.com>
# Copyright NuoBiT 2025 - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)


from odoo import api, models
from odoo.exceptions import ValidationError
from odoo.tools.translate import _


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

@api.constrains("default_code")
def _check_default_code(self):
for record in self:
if record.default_code:
domain = [
("default_code", "=", record.default_code),
("id", "!=", record.id),
]
if record.product_tmpl_id.company_id:
domain += [
"|",
(
"product_tmpl_id.company_id",
"=",
record.product_tmpl_id.company_id.id,
),
("product_tmpl_id.company_id", "=", False),
]
product = (
self.sudo()
.with_context(active_test=False)
.search(
domain,
limit=1,
)
)
if product:
raise ValidationError(
_(
"Error! The Default Code {} already exists. "
"Check also the archived ones."
).format(record.default_code)
)
46 changes: 46 additions & 0 deletions product_unique_internal_reference/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright NuoBiT - Eric Antones <eantones@nuobit.com>
# Copyright NuoBiT 2025 - Deniz Gallo <dgallo@nuobit.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)


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


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

@api.constrains("default_code", "company_id")
def _check_default_code(self):
for record in self:
if record.default_code:
# all products with the same default_code
products_all = (
self.env["product.product"]
.sudo()
.with_context(active_test=False)
.search(
[
("default_code", "=", record.default_code),
]
)
)
# products inside the same template
products_inside = products_all.filtered(
lambda p, record=record: p.product_tmpl_id == record
)
# products outside the same template
products_outside = products_all - products_inside
if record.company_id:
products_outside = products_outside.filtered(
lambda p, record=record: not p.product_tmpl_id.company_id
or p.product_tmpl_id.company_id == record.company_id
)
# check if the default code is used in other templates
if len(products_inside) > 1 or products_outside:
raise ValidationError(
_(
"Error! The Default Code {} already exists. "
"Check also the archived ones."
).format(record.default_code)
)
3 changes: 3 additions & 0 deletions product_unique_internal_reference/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
4 changes: 4 additions & 0 deletions product_unique_internal_reference/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- [NuoBiT](https://www.nuobit.com):
- Eric Antones <eantones@nuobit.com>
- Bijaya Kumal <bkumal@nuobit.com>
- Deniz Gallo <dgallo@nuobit.com>
3 changes: 3 additions & 0 deletions product_unique_internal_reference/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* This module ensures that you enter a 'Unique' Internal Reference (default_code)
for your Products.
* Multi company aware
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading