Arbore/arbore#155 add supplier name to purchase order lines in a separate column
This commit is contained in:
parent
8049272620
commit
fc3b037436
10 changed files with 338 additions and 0 deletions
50
product_supplier_name_purchase/README.md
Normal file
50
product_supplier_name_purchase/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Product Supplier Name in Purchase
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This module extends purchase order lines by adding the supplier's product name field. This allows users to see how the supplier refers to each product and enables sorting and filtering purchase order lines by the supplier's product name.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Supplier Product Name Field**: Displays the product name as defined by the supplier in the product supplier info
|
||||||
|
- **Automatic Computation**: The field is automatically computed based on the selected partner and product
|
||||||
|
- **Search and Filter**: Enables searching and filtering purchase order lines by supplier product name
|
||||||
|
- **Sortable Column**: Allows sorting purchase order lines by supplier product name
|
||||||
|
- **Multi-language Support**: Includes translations for Spanish, Catalan, and Galician
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Copy the module to your Odoo addons directory
|
||||||
|
2. Update the apps list in Odoo
|
||||||
|
3. Install the module from the Apps menu
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Go to Purchase → Purchase Orders
|
||||||
|
2. Create or edit a purchase order
|
||||||
|
3. Add purchase order lines with products that have supplier info configured
|
||||||
|
4. The "Supplier Product Name" column will automatically show the supplier's name for each product
|
||||||
|
5. Use this column to sort or filter the lines as needed
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Make sure your products have supplier information configured:
|
||||||
|
1. Go to Inventory → Products → Products
|
||||||
|
2. Select a product and go to the "Purchase" tab
|
||||||
|
3. Add vendor information with the supplier's product name
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
- **Model Extended**: `purchase.order.line`
|
||||||
|
- **New Field**: `product_supplier_name` (computed, stored)
|
||||||
|
- **Dependencies**: `purchase`
|
||||||
|
- **Version**: 16.0.1.0.0
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
**Criptomart**
|
||||||
|
- Maintainer: Luis Nore
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
|
||||||
4
product_supplier_name_purchase/__init__.py
Normal file
4
product_supplier_name_purchase/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright 2025 Criptomart
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from . import models
|
||||||
18
product_supplier_name_purchase/__manifest__.py
Normal file
18
product_supplier_name_purchase/__manifest__.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright 2025 Criptomart
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Product Supplier Name in Purchase",
|
||||||
|
"summary": """This module adds to the purchase order line the supplier
|
||||||
|
name defined in the product supplier info.""",
|
||||||
|
"version": "16.0.1.0.0",
|
||||||
|
"author": "Criptomart",
|
||||||
|
"maintainers": ["luisnore"],
|
||||||
|
"website": "https://github.com/criptomart",
|
||||||
|
"category": "Purchase Management",
|
||||||
|
"license": "AGPL-3",
|
||||||
|
"depends": ["purchase"],
|
||||||
|
"data": ["views/purchase_order_view.xml"],
|
||||||
|
"installable": True,
|
||||||
|
"development_status": "Beta",
|
||||||
|
}
|
||||||
38
product_supplier_name_purchase/i18n/ca.po
Normal file
38
product_supplier_name_purchase/i18n/ca.po
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Catalan translation for product_supplier_name_purchase.
|
||||||
|
# Copyright (C) 2025 Criptomart
|
||||||
|
# This file is distributed under the same license as the product_supplier_name_purchase package.
|
||||||
|
# Luis Nore <luisnore@criptomart.com>, 2025.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: product_supplier_name_purchase 16.0.1.0.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"PO-Revision-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"Last-Translator: Luis Nore <luisnore@criptomart.com>\n"
|
||||||
|
"Language-Team: Catalan\n"
|
||||||
|
"Language: ca\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_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,field_description:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Supplier Product Name"
|
||||||
|
msgstr "Nom del Producte del Proveïdor"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,help:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Product name as defined by the supplier in the product supplier info."
|
||||||
|
msgstr "Nom del producte segons el defineix el proveïdor en la informació de proveïdors del producte."
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order
|
||||||
|
msgid "Purchase Order"
|
||||||
|
msgstr "Ordre de Compra"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order_line
|
||||||
|
msgid "Purchase Order Line"
|
||||||
|
msgstr "Línia d'Ordre de Compra"
|
||||||
38
product_supplier_name_purchase/i18n/es.po
Normal file
38
product_supplier_name_purchase/i18n/es.po
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Spanish translation for product_supplier_name_purchase.
|
||||||
|
# Copyright (C) 2025 Criptomart
|
||||||
|
# This file is distributed under the same license as the product_supplier_name_purchase package.
|
||||||
|
# Luis Nore <luisnore@criptomart.com>, 2025.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: product_supplier_name_purchase 16.0.1.0.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"PO-Revision-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"Last-Translator: Luis Nore <luisnore@criptomart.com>\n"
|
||||||
|
"Language-Team: Spanish\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_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,field_description:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Supplier Product Name"
|
||||||
|
msgstr "Nombre Producto del Proveedor"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,help:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Product name as defined by the supplier in the product supplier info."
|
||||||
|
msgstr "Nombre del producto según lo define el proveedor en la información de proveedores del producto."
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order
|
||||||
|
msgid "Purchase Order"
|
||||||
|
msgstr "Orden de Compra"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order_line
|
||||||
|
msgid "Purchase Order Line"
|
||||||
|
msgstr "Línea de Orden de Compra"
|
||||||
38
product_supplier_name_purchase/i18n/gl.po
Normal file
38
product_supplier_name_purchase/i18n/gl.po
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Galician translation for product_supplier_name_purchase.
|
||||||
|
# Copyright (C) 2025 Criptomart
|
||||||
|
# This file is distributed under the same license as the product_supplier_name_purchase package.
|
||||||
|
# Luis Nore <luisnore@criptomart.com>, 2025.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: product_supplier_name_purchase 16.0.1.0.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"PO-Revision-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"Last-Translator: Luis Nore <luisnore@criptomart.com>\n"
|
||||||
|
"Language-Team: Galician\n"
|
||||||
|
"Language: gl\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_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,field_description:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Supplier Product Name"
|
||||||
|
msgstr "Nome do Produto do Provedor"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,help:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Product name as defined by the supplier in the product supplier info."
|
||||||
|
msgstr "Nome do produto segundo o define o provedor na información de provedores do produto."
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order
|
||||||
|
msgid "Purchase Order"
|
||||||
|
msgstr "Orde de Compra"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order_line
|
||||||
|
msgid "Purchase Order Line"
|
||||||
|
msgstr "Liña de Orde de Compra"
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Translation template for product_supplier_name_purchase.
|
||||||
|
# Copyright (C) 2025 Criptomart
|
||||||
|
# This file is distributed under the same license as the product_supplier_name_purchase package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: product_supplier_name_purchase 16.0.1.0.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2025-10-17 08:00+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,field_description:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Supplier Product Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model.fields,help:product_supplier_name_purchase.field_purchase_order_line__product_supplier_name
|
||||||
|
msgid "Product name as defined by the supplier in the product supplier info."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order
|
||||||
|
msgid "Purchase Order"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: product_supplier_name_purchase
|
||||||
|
#: model:ir.model,name:product_supplier_name_purchase.model_purchase_order_line
|
||||||
|
msgid "Purchase Order Line"
|
||||||
|
msgstr ""
|
||||||
4
product_supplier_name_purchase/models/__init__.py
Normal file
4
product_supplier_name_purchase/models/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright 2025 Criptomart
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from . import purchase_order
|
||||||
71
product_supplier_name_purchase/models/purchase_order.py
Normal file
71
product_supplier_name_purchase/models/purchase_order.py
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
# Copyright 2025 Criptomart
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
from odoo.exceptions import AccessError
|
||||||
|
|
||||||
|
|
||||||
|
class PurchaseOrderLine(models.Model):
|
||||||
|
_inherit = "purchase.order.line"
|
||||||
|
|
||||||
|
product_supplier_name = fields.Char(
|
||||||
|
string="Supplier Product Name",
|
||||||
|
compute="_compute_product_supplier_name",
|
||||||
|
store=True,
|
||||||
|
help="Product name as defined by the supplier in the product supplier info.",
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends("partner_id", "product_id")
|
||||||
|
def _compute_product_supplier_name(self):
|
||||||
|
for line in self:
|
||||||
|
name = ""
|
||||||
|
if line.product_id and line.partner_id:
|
||||||
|
# First try to find exact product match
|
||||||
|
supplier_info = line.product_id.seller_ids.filtered(
|
||||||
|
lambda s: (
|
||||||
|
s.product_id == line.product_id
|
||||||
|
and s.partner_id == line.partner_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if supplier_info:
|
||||||
|
name = supplier_info[0].product_name or ""
|
||||||
|
else:
|
||||||
|
# If no exact match, try product template
|
||||||
|
supplier_info = line.product_id.seller_ids.filtered(
|
||||||
|
lambda s: (
|
||||||
|
s.product_tmpl_id == line.product_id.product_tmpl_id
|
||||||
|
and s.partner_id == line.partner_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if supplier_info:
|
||||||
|
name = supplier_info[0].product_name or ""
|
||||||
|
line.product_supplier_name = name
|
||||||
|
|
||||||
|
|
||||||
|
class PurchaseOrder(models.Model):
|
||||||
|
_inherit = "purchase.order"
|
||||||
|
|
||||||
|
def _add_supplier_to_product(self):
|
||||||
|
"""Override to also update supplier product name when adding supplier."""
|
||||||
|
res = super()._add_supplier_to_product()
|
||||||
|
for line in self.order_line:
|
||||||
|
partner = (
|
||||||
|
self.partner_id
|
||||||
|
if not self.partner_id.parent_id
|
||||||
|
else self.partner_id.parent_id
|
||||||
|
)
|
||||||
|
if partner in line.product_id.seller_ids.mapped("partner_id"):
|
||||||
|
seller = line.product_id._select_seller(
|
||||||
|
partner_id=line.partner_id,
|
||||||
|
quantity=line.product_qty,
|
||||||
|
date=line.order_id.date_order and line.order_id.date_order.date(),
|
||||||
|
uom_id=line.product_uom,
|
||||||
|
)
|
||||||
|
if seller and hasattr(line, "product_supplier_name"):
|
||||||
|
try:
|
||||||
|
# Update supplier info with the current product name
|
||||||
|
if line.product_supplier_name:
|
||||||
|
seller.write({"product_name": line.product_supplier_name})
|
||||||
|
except AccessError:
|
||||||
|
break
|
||||||
|
return res
|
||||||
40
product_supplier_name_purchase/views/purchase_order_view.xml
Normal file
40
product_supplier_name_purchase/views/purchase_order_view.xml
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="purchase_order_form_supplier_name" model="ir.ui.view">
|
||||||
|
<field name="name">purchase.order.form.supplier.name</field>
|
||||||
|
<field name="model">purchase.order</field>
|
||||||
|
<field name="inherit_id" ref="purchase.purchase_order_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath
|
||||||
|
expr="//field[@name='order_line']//tree//field[@name='product_id']"
|
||||||
|
position="after"
|
||||||
|
>
|
||||||
|
<field name="product_supplier_name" optional="hide" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="purchase_order_line_tree_supplier_name" model="ir.ui.view">
|
||||||
|
<field name="name">purchase.order.line.tree.supplier.name</field>
|
||||||
|
<field name="model">purchase.order.line</field>
|
||||||
|
<field name="inherit_id" ref="purchase.purchase_order_line_tree" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<field name="product_id" position="after">
|
||||||
|
<field name="product_supplier_name" optional="show" />
|
||||||
|
</field>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="purchase_order_line_search_supplier_name" model="ir.ui.view">
|
||||||
|
<field name="name">purchase.order.line.search.supplier.name</field>
|
||||||
|
<field name="model">purchase.order.line</field>
|
||||||
|
<field name="inherit_id" ref="purchase.purchase_order_line_search" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<field name="product_id" position="after">
|
||||||
|
<field name="product_supplier_name" />
|
||||||
|
</field>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue