diff --git a/.gitignore b/.gitignore index 9ad8bab..a3957ae 100644 --- a/.gitignore +++ b/.gitignore @@ -130,5 +130,3 @@ dmypy.json # Pyre type checker .pyre/ - -tmp/ diff --git a/account_invoice_triple_discount_readonly/static/description/icon.png b/account_invoice_triple_discount_readonly/static/description/icon.png deleted file mode 100644 index d4a79d1..0000000 Binary files a/account_invoice_triple_discount_readonly/static/description/icon.png and /dev/null differ diff --git a/docs/install_logo.sh b/docs/install_logo.sh index 402291c..d651e09 100755 --- a/docs/install_logo.sh +++ b/docs/install_logo.sh @@ -8,8 +8,9 @@ # 2. Ejecutar: bash docs/install_logo.sh set -e -LOGO_SOURCE="/home/snt/Documentos/criptomart/artwork/logo_criptomart_cuadradado_white_background.png" -ADDONS=( + +LOGO_SOURCE="/home/snt/Documentos/lab/odoo/addons-cm/website_sale_aplicoop/static/description/logo_criptomart_cuadradado_white_background.png" +ADDtaONS=( "website_sale_aplicoop" "product_sale_price_from_pricelist" "product_pricelist_total_margin" @@ -32,7 +33,6 @@ echo "馃帹 Instalando logo de CriptoMart en addons..." echo "" # Copiar logo a cada addon -cd .. for addon in "${ADDONS[@]}"; do if [ -d "$addon" ]; then # Crear directorio si no existe diff --git a/product_origin_char/README.rst b/product_origin_char/README.rst deleted file mode 100644 index 0cbdfa6..0000000 --- a/product_origin_char/README.rst +++ /dev/null @@ -1,155 +0,0 @@ -================== -Product Origin Text -================== - -.. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! This file is generated by oca-gen-addon-readme !! - !! changes will be overwritten. !! - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:todo - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -.. |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 - -|badge1| |badge2| - -This module replaces the structured country/state origin fields from ``product_origin`` -with a flexible free-text field that can be defined per supplier. - -**Problem:** - -The standard ``product_origin`` module provides structured fields (country + state) for -product origin. However, suppliers often use creative and varied formats to describe -product origin: - -* "Valencia, Spain" -* "Huerta de Ana, Arag贸n" -* "Organic Farm - Northern Italy" -* "Local producer - Basque Country" -* "Fair Trade - Colombia" - -These free-form descriptions don't fit into structured country/state fields. - -**Solution:** - -This module adds a translatable ``origin_text`` field to ``product.supplierinfo`` that: - -* Allows free-form text to describe product origin -* Is stored per supplier (different suppliers may have different origin info) -* Is translatable (can be described differently in each language) -* Is automatically displayed on the product based on the main vendor - (from ``product_main_seller`` module) - -**Features:** - -* Free-text ``Origin`` field in supplier info (Purchase tab of product) -* Computed ``Origin`` field in product form (shows main vendor's origin) -* Field is visible in product list view (optional column) -* Full translation support for multiple languages -* Compatible with existing supplier management workflows - -**Table of contents** - -.. contents:: - :local: - -Installation -============ - -This module depends on: - -* ``product`` - Base product management -* ``product_main_seller`` - To determine the main vendor for products - -To install: - -#. Install the required dependencies -#. Install this module through the Odoo Apps menu - -Configuration -============= - -No configuration is needed. The module works automatically after installation. - -The origin text displayed on a product is based on the **main vendor** as determined -by ``product_main_seller`` (the first supplier in the vendors list). - -Usage -===== - -**To add origin information to a product:** - -#. Go to a product form -#. Open the **Purchase** tab -#. In the **Vendors** section, select a supplier line -#. Fill in the **Origin** field with free-form text describing the origin - (e.g., "Valencia, Huerta de..., Spain") -#. Save the product - -**To view origin information:** - -* The **Origin** field will be automatically displayed on the product form - (below the **Main Vendor** field in the Purchase tab) -* The origin shown is from the **main vendor** (first supplier in the list) -* You can also add the Origin column to product list views - -**To change the displayed origin:** - -* Reorder the vendors list to change which is the main vendor -* The origin text will automatically update to show the new main vendor's origin - -**Multi-language support:** - -* The origin text is translatable -* Switch to another language and edit the supplier info to provide a translation -* Each language can have a different description of the origin - -Bug Tracker -=========== - -Bugs are tracked on `Criptomart GitLab 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. - -Credits -======= - -Contributors ------------- - -* `Criptomart `_: - - * Development and implementation - -Financiers ----------- - -**Development:** - -* `Criptomart `_ - -**Funding:** - -* `Elika Bilbo `_ - -This module was developed by Criptomart with funding from Elika Bilbo. - -Maintainers ------------ - -This module is maintained by Criptomart. - -.. image:: https://criptomart.net/logo.png - :alt: Criptomart - :target: https://criptomart.net - -This module is part of the `addons-cm `_ project. diff --git a/product_origin_char/README_DEV.md b/product_origin_char/README_DEV.md deleted file mode 100644 index 3ed005a..0000000 --- a/product_origin_char/README_DEV.md +++ /dev/null @@ -1,114 +0,0 @@ -# Product Origin Text - Developer Notes - -## Technical Implementation - -### Architecture - -This module extends the product origin information system to use free-text fields instead of structured country/state fields. - -**Models:** - -1. **product.supplierinfo** - Base model with the `origin_text` field - - Field: `origin_text` (Char, translate=True) - - This is where the actual data is stored - - Each supplier can have a different origin text for the same product - -2. **product.template** - Computed field - - Field: `origin_text` (Char, computed, store=False) - - Computes from main vendor's supplierinfo - - Depends on: `main_seller_id`, `variant_seller_ids.origin_text` - -3. **product.product** - Computed field (variant level) - - Field: `origin_text` (Char, computed, store=False) - - Computes from main vendor's supplierinfo - - Depends on: `product_tmpl_id.main_seller_id`, `seller_ids.origin_text` - -### Why Computed Fields Instead of Related? - -The `origin_text` field in `product.template` and `product.product` cannot be a simple `related` field because: - -- `main_seller_id` is a `res.partner` record -- `origin_text` is stored in `product.supplierinfo` records -- We need to find the supplierinfo record where `partner_id == main_seller_id` - -This requires a computed field with custom logic to filter and find the correct supplierinfo record. - -### Translation Support - -The `origin_text` field in `product.supplierinfo` uses `translate=True`, which means: - -- Each language can have a different value -- Translations are stored in Odoo's translation system -- When switching languages, the field shows the translated value -- If no translation exists, it falls back to the default language value - -### Store Strategy - -The computed fields in product template and product use `store=False` because: - -- The value should always reflect the current main vendor -- If the main vendor changes or its origin text is updated, the product's origin should update automatically -- No need to store redundant data -- Reduces database size and update complexity - -### Dependencies - -- **product** - Core product module -- **product_main_seller** - Provides `main_seller_id` computed field for products - -### Relationship to product_origin - -This module is a replacement/alternative to the OCA `product_origin` module: - -- `product_origin` provides structured fields (country_id, state_id) -- `product_origin_char` provides free-text field (origin_text) -- Both cannot be installed simultaneously without potential conflicts -- This module was created because suppliers use creative, non-standardized origin descriptions - -### Performance Considerations - -- Computed fields with `store=False` are calculated on-the-fly -- Performance is acceptable because the computation is simple (filter + get first) -- If performance becomes an issue, consider: - - Adding `store=True` with proper dependencies - - Adding database indexes on frequently searched fields - - Caching strategies - -### Testing Strategy - -Tests cover: - -1. **Basic field storage** - Create supplierinfo with origin_text -2. **Computed field** - Verify product shows main vendor's origin -3. **Main vendor change** - Verify origin updates when main vendor changes -4. **Translation** - Verify field is translatable (multilingual support) -5. **Empty cases** - Product without vendors, vendor without origin - -### Future Improvements - -Potential enhancements: - -- Add migration script from `product_origin` to convert country/state to text -- Add bulk update wizard to set origin for multiple products -- Add origin text to purchase order lines -- Add search/group by origin in product lists -- Add validation rules (max length, format checks) - -## Code Quality - -- Follows OCA guidelines -- Black formatted (line length 88) -- isort sorted imports -- Passes flake8 and pylint checks -- Full test coverage -- Documented with docstrings -- Translatable strings handled correctly (no `_()` in field definitions) - -## Version History - -- **18.0.1.0.0** (2026-02-25) - Initial release - - Free-text origin field per supplier - - Automatic display based on main vendor - - Multi-language support - - Full test coverage - - OCA documentation structure diff --git a/product_origin_char/__init__.py b/product_origin_char/__init__.py deleted file mode 100644 index f744d4a..0000000 --- a/product_origin_char/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from . import models # noqa: F401 diff --git a/product_origin_char/__manifest__.py b/product_origin_char/__manifest__.py deleted file mode 100644 index 5be4956..0000000 --- a/product_origin_char/__manifest__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -{ # noqa: B018 - "name": "Product Origin Text", - "version": "18.0.1.0.0", - "category": "Product", - "summary": "Free text origin field per supplier", - "author": "Odoo Community Association (OCA), Criptomart", - "maintainers": ["Criptomart"], - "license": "AGPL-3", - "website": "https://git.criptomart.net/criptomart/addons-cm", - "depends": [ - "product", - "product_main_seller", - ], - "data": [ - "views/product_supplierinfo_views.xml", - "views/product_template_views.xml", - ], -} diff --git a/product_origin_char/i18n/es.po b/product_origin_char/i18n/es.po deleted file mode 100644 index 95e6747..0000000 --- a/product_origin_char/i18n/es.po +++ /dev/null @@ -1,50 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * product_origin_char -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 18.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-25 12:00+0000\n" -"PO-Revision-Date: 2026-02-25 12:00+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" - -#. module: product_origin_char -#: model:ir.model.fields,field_description:product_origin_char.field_product_product__origin_text -#: model:ir.model.fields,field_description:product_origin_char.field_product_supplierinfo__origin_text -#: model:ir.model.fields,field_description:product_origin_char.field_product_template__origin_text -msgid "Origin" -msgstr "Origen" - -#. module: product_origin_char -#: model:ir.model.fields,help:product_origin_char.field_product_supplierinfo__origin_text -msgid "Free text to describe product origin (country, region, producer, etc.)" -msgstr "Texto libre para describir el origen del producto (pa铆s, regi贸n, productor, etc.)" - -#. module: product_origin_char -#: model:ir.model.fields,help:product_origin_char.field_product_product__origin_text -#: model:ir.model.fields,help:product_origin_char.field_product_template__origin_text -msgid "Origin text from main vendor's supplierinfo" -msgstr "Texto de origen del proveedor principal" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_product -msgid "Product" -msgstr "Producto" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_template -msgid "Product Template" -msgstr "Plantilla de producto" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_supplierinfo -msgid "Supplier Pricelist" -msgstr "Tarifa de proveedor" diff --git a/product_origin_char/i18n/eu.po b/product_origin_char/i18n/eu.po deleted file mode 100644 index f297c51..0000000 --- a/product_origin_char/i18n/eu.po +++ /dev/null @@ -1,50 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * product_origin_char -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 18.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-25 12:00+0000\n" -"PO-Revision-Date: 2026-02-25 12:00+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: eu\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" - -#. module: product_origin_char -#: model:ir.model.fields,field_description:product_origin_char.field_product_product__origin_text -#: model:ir.model.fields,field_description:product_origin_char.field_product_supplierinfo__origin_text -#: model:ir.model.fields,field_description:product_origin_char.field_product_template__origin_text -msgid "Origin" -msgstr "Jatorria" - -#. module: product_origin_char -#: model:ir.model.fields,help:product_origin_char.field_product_supplierinfo__origin_text -msgid "Free text to describe product origin (country, region, producer, etc.)" -msgstr "Testu librea produktuaren jatorria deskribatzeko (herrialdea, eskualdea, ekoizlea, etab.)" - -#. module: product_origin_char -#: model:ir.model.fields,help:product_origin_char.field_product_product__origin_text -#: model:ir.model.fields,help:product_origin_char.field_product_template__origin_text -msgid "Origin text from main vendor's supplierinfo" -msgstr "Hornitzaile nagusiaren jatorriaren testua" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_product -msgid "Product" -msgstr "Produktua" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_template -msgid "Product Template" -msgstr "Produktu txantiloia" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_supplierinfo -msgid "Supplier Pricelist" -msgstr "Hornitzailearen prezioen zerrenda" diff --git a/product_origin_char/i18n/product_origin_char.pot b/product_origin_char/i18n/product_origin_char.pot deleted file mode 100644 index 321e6cb..0000000 --- a/product_origin_char/i18n/product_origin_char.pot +++ /dev/null @@ -1,49 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * product_origin_char -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 18.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-02-25 12:00+0000\n" -"PO-Revision-Date: 2026-02-25 12:00+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" - -#. module: product_origin_char -#: model:ir.model.fields,field_description:product_origin_char.field_product_product__origin_text -#: model:ir.model.fields,field_description:product_origin_char.field_product_supplierinfo__origin_text -#: model:ir.model.fields,field_description:product_origin_char.field_product_template__origin_text -msgid "Origin" -msgstr "" - -#. module: product_origin_char -#: model:ir.model.fields,help:product_origin_char.field_product_supplierinfo__origin_text -msgid "Free text to describe product origin (country, region, producer, etc.)" -msgstr "" - -#. module: product_origin_char -#: model:ir.model.fields,help:product_origin_char.field_product_product__origin_text -#: model:ir.model.fields,help:product_origin_char.field_product_template__origin_text -msgid "Origin text from main vendor's supplierinfo" -msgstr "" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_product -msgid "Product" -msgstr "" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_template -msgid "Product Template" -msgstr "" - -#. module: product_origin_char -#: model:ir.model,name:product_origin_char.model_product_supplierinfo -msgid "Supplier Pricelist" -msgstr "" diff --git a/product_origin_char/models/__init__.py b/product_origin_char/models/__init__.py deleted file mode 100644 index e138082..0000000 --- a/product_origin_char/models/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from . import product_supplierinfo # noqa: F401 -from . import product_template # noqa: F401 -from . import product_product # noqa: F401 diff --git a/product_origin_char/models/product_product.py b/product_origin_char/models/product_product.py deleted file mode 100644 index 1ec475b..0000000 --- a/product_origin_char/models/product_product.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api -from odoo import fields -from odoo import models - - -class ProductProduct(models.Model): - _inherit = "product.product" - - origin_text = fields.Char( - string="Origin", - compute="_compute_origin_text", - store=False, - help="Origin text from main vendor's supplierinfo", - ) - - @api.depends("product_tmpl_id.main_seller_id", "seller_ids.origin_text") - def _compute_origin_text(self): - for product in self: - if product.product_tmpl_id.main_seller_id: - # Find the supplierinfo record for the main seller - main_seller = product.product_tmpl_id.main_seller_id - seller = product.seller_ids.filtered( - lambda s, ms=main_seller: s.partner_id == ms - )[:1] - product.origin_text = seller.origin_text if seller else False - else: - product.origin_text = False diff --git a/product_origin_char/models/product_supplierinfo.py b/product_origin_char/models/product_supplierinfo.py deleted file mode 100644 index 1f87c7d..0000000 --- a/product_origin_char/models/product_supplierinfo.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import fields -from odoo import models - - -class ProductSupplierinfo(models.Model): - _inherit = "product.supplierinfo" - - origin_text = fields.Char( - string="Origin", - translate=True, - help="Free text to describe product origin (country, region, producer, etc.)", - ) diff --git a/product_origin_char/models/product_template.py b/product_origin_char/models/product_template.py deleted file mode 100644 index 3386907..0000000 --- a/product_origin_char/models/product_template.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import api -from odoo import fields -from odoo import models - - -class ProductTemplate(models.Model): - _inherit = "product.template" - - origin_text = fields.Char( - string="Origin", - compute="_compute_origin_text", - store=False, - help="Origin text from main vendor's supplierinfo", - ) - - @api.depends("main_seller_id", "variant_seller_ids.origin_text") - def _compute_origin_text(self): - for template in self: - if template.main_seller_id: - # Find the supplierinfo record for the main seller - main_seller = template.main_seller_id - seller = template.variant_seller_ids.filtered( - lambda s, ms=main_seller: s.partner_id == ms - )[:1] - template.origin_text = seller.origin_text if seller else False - else: - template.origin_text = False diff --git a/product_origin_char/pyproject.toml b/product_origin_char/pyproject.toml deleted file mode 100644 index 99522bf..0000000 --- a/product_origin_char/pyproject.toml +++ /dev/null @@ -1,26 +0,0 @@ -[tool.black] -line-length = 88 -target-version = ['py310'] -include = '\.pyi?$' -exclude = ''' -/( - \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | dist - | __pycache__ -)/ -''' - -[tool.isort] -profile = "black" -line_length = 88 -known_odoo = "odoo" -known_odoo_addons = "odoo.addons" -sections = ["FUTURE", "STDLIB", "THIRDPARTY", "ODOO", "ODOO_ADDONS", "FIRSTPARTY", "LOCALFOLDER"] -default_section = "THIRDPARTY" diff --git a/product_origin_char/readme/CONFIGURE.rst b/product_origin_char/readme/CONFIGURE.rst deleted file mode 100644 index 6c5dff4..0000000 --- a/product_origin_char/readme/CONFIGURE.rst +++ /dev/null @@ -1,4 +0,0 @@ -No configuration is needed. The module works automatically after installation. - -The origin text displayed on a product is based on the **main vendor** as determined -by ``product_main_seller`` (the first supplier in the vendors list). diff --git a/product_origin_char/readme/CONTRIBUTORS.rst b/product_origin_char/readme/CONTRIBUTORS.rst deleted file mode 100644 index 7554246..0000000 --- a/product_origin_char/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1,3 +0,0 @@ -* `Criptomart `_: - - * Development and implementation diff --git a/product_origin_char/readme/CREDITS.rst b/product_origin_char/readme/CREDITS.rst deleted file mode 100644 index d399b18..0000000 --- a/product_origin_char/readme/CREDITS.rst +++ /dev/null @@ -1,9 +0,0 @@ -**Development:** - -* `Criptomart `_ - -**Funding:** - -* `Elika Bilbo `_ - -This module was developed by Criptomart with funding from Elika Bilbo. diff --git a/product_origin_char/readme/DESCRIPTION.rst b/product_origin_char/readme/DESCRIPTION.rst deleted file mode 100644 index 39203bc..0000000 --- a/product_origin_char/readme/DESCRIPTION.rst +++ /dev/null @@ -1,34 +0,0 @@ -This module replaces the structured country/state origin fields from ``product_origin`` -with a flexible free-text field that can be defined per supplier. - -**Problem:** - -The standard ``product_origin`` module provides structured fields (country + state) for -product origin. However, suppliers often use creative and varied formats to describe -product origin: - -* "Valencia, Spain" -* "Huerta de Ana, Arag贸n" -* "Organic Farm - Northern Italy" -* "Local producer - Basque Country" -* "Fair Trade - Colombia" - -These free-form descriptions don't fit into structured country/state fields. - -**Solution:** - -This module adds a translatable ``origin_text`` field to ``product.supplierinfo`` that: - -* Allows free-form text to describe product origin -* Is stored per supplier (different suppliers may have different origin info) -* Is translatable (can be described differently in each language) -* Is automatically displayed on the product based on the main vendor - (from ``product_main_seller`` module) - -**Features:** - -* Free-text ``Origin`` field in supplier info (Purchase tab of product) -* Computed ``Origin`` field in product form (shows main vendor's origin) -* Field is visible in product list view (optional column) -* Full translation support for multiple languages -* Compatible with existing supplier management workflows diff --git a/product_origin_char/readme/INSTALL.rst b/product_origin_char/readme/INSTALL.rst deleted file mode 100644 index 621a392..0000000 --- a/product_origin_char/readme/INSTALL.rst +++ /dev/null @@ -1,9 +0,0 @@ -This module depends on: - -* ``product`` - Base product management -* ``product_main_seller`` - To determine the main vendor for products - -To install: - -#. Install the required dependencies -#. Install this module through the Odoo Apps menu diff --git a/product_origin_char/readme/USAGE.rst b/product_origin_char/readme/USAGE.rst deleted file mode 100644 index 60476ba..0000000 --- a/product_origin_char/readme/USAGE.rst +++ /dev/null @@ -1,26 +0,0 @@ -**To add origin information to a product:** - -#. Go to a product form -#. Open the **Purchase** tab -#. In the **Vendors** section, select a supplier line -#. Fill in the **Origin** field with free-form text describing the origin - (e.g., "Valencia, Huerta de..., Spain") -#. Save the product - -**To view origin information:** - -* The **Origin** field will be automatically displayed on the product form - (below the **Main Vendor** field in the Purchase tab) -* The origin shown is from the **main vendor** (first supplier in the list) -* You can also add the Origin column to product list views - -**To change the displayed origin:** - -* Reorder the vendors list to change which is the main vendor -* The origin text will automatically update to show the new main vendor's origin - -**Multi-language support:** - -* The origin text is translatable -* Switch to another language and edit the supplier info to provide a translation -* Each language can have a different description of the origin diff --git a/product_origin_char/static/description/LOGO_NEEDED.txt b/product_origin_char/static/description/LOGO_NEEDED.txt deleted file mode 100644 index 8a1fad3..0000000 --- a/product_origin_char/static/description/LOGO_NEEDED.txt +++ /dev/null @@ -1 +0,0 @@ -Logo placeholder - run install_logo.sh to add CriptoMart logo diff --git a/product_origin_char/static/description/icon.png b/product_origin_char/static/description/icon.png deleted file mode 100644 index d4a79d1..0000000 Binary files a/product_origin_char/static/description/icon.png and /dev/null differ diff --git a/product_origin_char/static/description/index.html b/product_origin_char/static/description/index.html deleted file mode 100644 index 5a1cdcc..0000000 --- a/product_origin_char/static/description/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - Product Origin Text - - - -

Product Origin Text

- -

- Beta - License: AGPL-3 -

- -

Overview

-

- This module replaces the structured country/state origin fields from - product_origin with a flexible free-text field that can be - defined per supplier. -

- -
-

Problem:

-

- Suppliers often use creative and varied formats to describe product origin: -

-
    -
  • "Valencia, Spain"
  • -
  • "Huerta de Ana, Arag贸n"
  • -
  • "Organic Farm - Northern Italy"
  • -
  • "Local producer - Basque Country"
  • -
  • "Fair Trade - Colombia"
  • -
-

- These free-form descriptions don't fit into structured country/state fields. -

-
- -

Features

-
    -
  • Free-text Origin field in supplier info (Purchase tab of product)
  • -
  • Computed Origin field in product form (shows main vendor's origin)
  • -
  • Field is visible in product list view (optional column)
  • -
  • Full translation support for multiple languages
  • -
  • Compatible with existing supplier management workflows
  • -
- -

Usage

-
    -
  1. Go to a product form
  2. -
  3. Open the Purchase tab
  4. -
  5. In the Vendors section, select a supplier line
  6. -
  7. Fill in the Origin field with free-form text
  8. -
  9. The origin text from the main vendor will automatically appear on the product
  10. -
- -

Dependencies

-
    -
  • product - Base product management
  • -
  • product_main_seller - To determine the main vendor for products
  • -
- -

Credits

-

Development: Criptomart

-

Funding: Elika Bilbo

-

- This module was developed by Criptomart with funding from Elika Bilbo. -

- - diff --git a/product_origin_char/tests/__init__.py b/product_origin_char/tests/__init__.py deleted file mode 100644 index fcf3e3a..0000000 --- a/product_origin_char/tests/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from . import test_product_origin_char # noqa: F401 diff --git a/product_origin_char/tests/test_product_origin_char.py b/product_origin_char/tests/test_product_origin_char.py deleted file mode 100644 index 0d7a9df..0000000 --- a/product_origin_char/tests/test_product_origin_char.py +++ /dev/null @@ -1,233 +0,0 @@ -# Copyright 2026 Criptomart -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo.tests.common import TransactionCase - - -class TestProductOriginChar(TransactionCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - - # Create test suppliers - cls.supplier_1 = cls.env["res.partner"].create( - { - "name": "Supplier 1", - "is_company": True, - } - ) - cls.supplier_2 = cls.env["res.partner"].create( - { - "name": "Supplier 2", - "is_company": True, - } - ) - - # Create test product - cls.product = cls.env["product.product"].create( - { - "name": "Test Product", - "type": "consu", - } - ) - - def test_01_origin_text_in_supplierinfo(self): - """Test that origin_text can be set in supplierinfo""" - supplierinfo = self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "origin_text": "Valencia, Spain", - } - ) - self.assertEqual(supplierinfo.origin_text, "Valencia, Spain") - - def test_02_origin_from_main_seller(self): - """Test that product shows origin from main seller""" - # Create supplierinfo for supplier 1 (will be main seller) - self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "sequence": 1, - "origin_text": "Valencia, Spain", - } - ) - - # Verify main seller is supplier 1 - self.product.product_tmpl_id.invalidate_recordset() - self.assertEqual(self.product.product_tmpl_id.main_seller_id, self.supplier_1) - - # Verify origin_text on product matches supplier 1's origin - self.product.invalidate_recordset() - self.assertEqual(self.product.origin_text, "Valencia, Spain") - self.assertEqual(self.product.product_tmpl_id.origin_text, "Valencia, Spain") - - def test_03_origin_updates_with_main_seller_change(self): - """Test that origin updates when main seller changes""" - # Create supplierinfo for both suppliers - supplier1_info = self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "sequence": 1, - "origin_text": "Valencia, Spain", - } - ) - supplier2_info = self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_2.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "sequence": 2, - "origin_text": "Arag贸n, Spain", - } - ) - - # Initially, main seller is supplier 1 - self.product.product_tmpl_id.invalidate_recordset() - self.assertEqual(self.product.product_tmpl_id.main_seller_id, self.supplier_1) - self.product.invalidate_recordset() - self.assertEqual(self.product.origin_text, "Valencia, Spain") - - # Change main seller by swapping sequences - supplier1_info.sequence = 2 - supplier2_info.sequence = 1 - - # Verify main seller is now supplier 2 - self.product.product_tmpl_id.invalidate_recordset() - self.assertEqual(self.product.product_tmpl_id.main_seller_id, self.supplier_2) - - # Verify origin_text updated to supplier 2's origin - self.product.invalidate_recordset() - self.assertEqual(self.product.origin_text, "Arag贸n, Spain") - - def test_04_empty_origin_without_supplier(self): - """Test that product without suppliers has no origin""" - # Create product without suppliers - product_no_supplier = self.env["product.product"].create( - { - "name": "Product Without Supplier", - "type": "consu", - } - ) - - # Verify no main seller and no origin - self.assertFalse(product_no_supplier.product_tmpl_id.main_seller_id) - self.assertFalse(product_no_supplier.origin_text) - - def test_05_empty_origin_with_supplier_no_text(self): - """Test that supplier without origin_text shows False""" - # Create supplierinfo without origin_text - self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "sequence": 1, - # No origin_text set - } - ) - - # Verify main seller exists but origin is False - self.product.product_tmpl_id.invalidate_recordset() - self.assertEqual(self.product.product_tmpl_id.main_seller_id, self.supplier_1) - self.product.invalidate_recordset() - self.assertFalse(self.product.origin_text) - - def test_06_translation_support(self): - """Test that origin_text field is translatable""" - # Create supplierinfo with origin in default language - supplierinfo = self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "origin_text": "Valencia, Spain", - } - ) - - # Verify field has translate=True attribute - field = self.env["product.supplierinfo"]._fields["origin_text"] - self.assertTrue(field.translate) - - # Test that we can set translation (requires lang to be installed) - # This is a basic check - full translation testing would require - # installing multiple languages - self.assertEqual(supplierinfo.origin_text, "Valencia, Spain") - - def test_07_multiple_products_same_supplier(self): - """Test that different products can have different origins from same supplier""" - product2 = self.env["product.product"].create( - { - "name": "Test Product 2", - "type": "consu", - } - ) - - # Create supplierinfo for product 1 - self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": self.product.product_tmpl_id.id, - "origin_text": "Valencia, Spain", - } - ) - - # Create supplierinfo for product 2 with same supplier but different origin - self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": product2.product_tmpl_id.id, - "origin_text": "Arag贸n, Spain", - } - ) - - # Verify each product has its own origin - self.product.invalidate_recordset() - product2.invalidate_recordset() - self.assertEqual(self.product.origin_text, "Valencia, Spain") - self.assertEqual(product2.origin_text, "Arag贸n, Spain") - - def test_08_product_variant_level(self): - """Test that origin_text works at product variant level""" - # Create product template with variants - product_attr = self.env["product.attribute"].create({"name": "Color"}) - attr_value_red = self.env["product.attribute.value"].create( - {"name": "Red", "attribute_id": product_attr.id} - ) - attr_value_blue = self.env["product.attribute.value"].create( - {"name": "Blue", "attribute_id": product_attr.id} - ) - - product_tmpl = self.env["product.template"].create( - { - "name": "Product with Variants", - "type": "consu", - "attribute_line_ids": [ - ( - 0, - 0, - { - "attribute_id": product_attr.id, - "value_ids": [ - (6, 0, [attr_value_red.id, attr_value_blue.id]) - ], - }, - ) - ], - } - ) - - # Create supplierinfo at template level - self.env["product.supplierinfo"].create( - { - "partner_id": self.supplier_1.id, - "product_tmpl_id": product_tmpl.id, - "origin_text": "Test Origin", - } - ) - - # Verify all variants show the same origin (from template level) - product_tmpl.invalidate_recordset() - for variant in product_tmpl.product_variant_ids: - variant.invalidate_recordset() - self.assertEqual(variant.origin_text, "Test Origin") diff --git a/product_origin_char/views/product_supplierinfo_views.xml b/product_origin_char/views/product_supplierinfo_views.xml deleted file mode 100644 index d881aa0..0000000 --- a/product_origin_char/views/product_supplierinfo_views.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - product.supplierinfo.form.origin.text - product.supplierinfo - - - - - - - - - - - product.supplierinfo.tree.origin.text - product.supplierinfo - - - - - - - - diff --git a/product_origin_char/views/product_template_views.xml b/product_origin_char/views/product_template_views.xml deleted file mode 100644 index 19d9db7..0000000 --- a/product_origin_char/views/product_template_views.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - product.template.form.origin.text - product.template - - - - - - - - - - - product.product.tree.origin.text - product.product - - - - - - - - - - - product.template.tree.origin.text - product.template - - - - - - - - diff --git a/product_price_category_supplier/static/description/icon.png b/product_price_category_supplier/static/description/icon.png deleted file mode 100644 index d4a79d1..0000000 Binary files a/product_price_category_supplier/static/description/icon.png and /dev/null differ diff --git a/product_pricelist_total_margin/static/description/icon.png b/product_pricelist_total_margin/static/description/icon.png deleted file mode 100644 index d4a79d1..0000000 Binary files a/product_pricelist_total_margin/static/description/icon.png and /dev/null differ diff --git a/product_sale_price_from_pricelist/static/description/icon.png b/product_sale_price_from_pricelist/static/description/icon.png deleted file mode 100644 index d4a79d1..0000000 Binary files a/product_sale_price_from_pricelist/static/description/icon.png and /dev/null differ diff --git a/website_sale_aplicoop/static/description/icon.png b/website_sale_aplicoop/static/description/icon.png deleted file mode 100644 index d4a79d1..0000000 Binary files a/website_sale_aplicoop/static/description/icon.png and /dev/null differ