Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
==========================
Product customer info sale
==========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4d8f8f9641e008b30e802648977d0f2cef06d502d2558c62ef5ee64a1ee533fe
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/18.0/product_customerinfo_sale
: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-18-0/sale-workflow-18-0-product_customerinfo_sale
: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=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
Based on product_customerinfo, this module loads in every sale order the
customer code defined in the product and allows use the product codes
and product name configured in each products in sale orders.
If you use Advanced price rules with formulas to define your pricing,
and choose that the price should be calculated from the partner prices
in the product form, the quantity in the sales order will be proposed
from the minimum quantity defined in the customerinfo.
**Table of contents**
.. contents::
:local:
Usage
=====
To use this module, you need:
- Go to product and configure *Partner product name* and *Partner
product code* for each selected customer.
|image1|
- When add order lines in sale quotation for a customer that has an
specific name and code in the product, you can search that product
with that customer name or code. Then, this values will be displayed
in product description.
|image2|
|image3|
- If product does not have a configuration for customer selected,
product will be search by its default code.
|image4|
|image5|
.. |image1| image:: https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/configuration_customer.png
.. |image2| image:: https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/search_code.png
.. |image3| image:: https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/description_code.png
.. |image4| image:: https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/search_code_2.png
.. |image5| image:: https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/description_code_2.png
Known issues / Roadmap
======================
- Putting a minimum qty in a pricelist rule means the system will use
the option 'list price' instead of any option you chose.
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:%20product_customerinfo_sale%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
-------
* Agile Business Group
* Vauxoo
Contributors
------------
- Xavier Jimenez <xavier.jimenez@qubiq.es>
- Nicola Malcontenti <nicola.malcontenti@agilebg.com>
- Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
- Moisés López <moylop260@vauxoo.com>
- Yennifer Santiago <yennifer@vauxoo.com>
- Julio Serna Hernández <julio@vauxoo.com>
- Sergio Teruel <sergio.teruel@tecnativa.com>
- Lois Rilo <lois.rilo@forgeflow.com>
- Juany Davila <juany.davila@forgeflow.com>
- Carlos Reyes <carlos@studio73.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/18.0/product_customerinfo_sale>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

View File

@@ -0,0 +1,21 @@
# Copyright 2013-2017 Agile Business Group sagl
# (<http://www.agilebg.com>)
# Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Product customer info sale",
"version": "18.0.1.0.0",
"summary": "Loads in every sale order line the customer code defined "
"in the product",
"author": "Agile Business Group,Vauxoo,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/sale-workflow",
"category": "Sales Management",
"license": "AGPL-3",
"depends": ["sale", "product_customerinfo"],
"data": [
"security/ir.model.access.csv",
"views/product_customerinfo_views.xml",
"views/sale_view.xml",
],
"installable": True,
}

View File

@@ -0,0 +1,49 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_supplierinfo_for_customer_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2021-03-10 10:45+0000\n"
"Last-Translator: Daniel Martinez Vila <daniel.martinez@qubiq.es>\n"
"Language-Team: none\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: product_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr ""
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr "Codi de client del producte"
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Línia de comanda de vendes"
#~ msgid ""
#~ "Check this box if this contact is a customer. It can be selected in sales "
#~ "orders."
#~ msgstr ""
#~ "Marqueu aquesta casella si aquest contacte és client. Es pot seleccionar "
#~ "en comandes de venda."
#~ msgid "Is a Customer"
#~ msgstr "És client"
#~ msgid "Product Template"
#~ msgstr "Plantilla del Producte"
#~ msgid "Supplierinfo"
#~ msgstr "Informació del proveïdor"

View File

@@ -0,0 +1,36 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_supplierinfo_for_customer_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-10-11 11:38+0000\n"
"Last-Translator: David Brühlmeier <david@bruehlmeier.com>\n"
"Language-Team: none\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: product_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr "Kundenpreise"
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr "Kundencode des Produkts"
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Auftragsposition"
#~ msgid "Product"
#~ msgstr "Produkt"

View File

@@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_supplierinfo_for_customer_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-16 13:31+0000\n"
"PO-Revision-Date: 2022-06-16 15:32+0200\n"
"Last-Translator: Daniel Martinez Vila <daniel.martinez@qubiq.es>\n"
"Language-Team: none\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"
"X-Generator: Poedit 2.3\n"
#. module: product_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr "Precios para clientes"
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr "Código de cliente del producto"
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Línea pedido de venta"
#~ msgid ""
#~ "Check this box if this contact is a customer. It can be selected in sales "
#~ "orders."
#~ msgstr ""
#~ "Marque esta casilla si este contacto es un cliente. Se puede seleccionar "
#~ "en pedidos de cliente."
#~ msgid "Product Template"
#~ msgstr "Plantilla de producto"
#~ msgid "Supplierinfo"
#~ msgstr "Información del proveedor"

View File

@@ -0,0 +1,51 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * product_customer_code_sale
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-01-15 14:31+0000\n"
"PO-Revision-Date: 2023-12-01 15:35+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: \n"
"Language: it\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"
"X-Generator: Weblate 4.17\n"
"X-Launchpad-Export-Date: 2014-05-28 05:52+0000\n"
#. module: product_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr "Prezzi per i clienti"
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr "Codice cliente prodotto"
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Riga ordine di vendita"
#~ msgid ""
#~ "Check this box if this contact is a customer. It can be selected in sales "
#~ "orders."
#~ msgstr ""
#~ "Attivare se il contatto è un cliente. Può essere selezionato negli ordini "
#~ "di vendita."
#~ msgid "Is a Customer"
#~ msgstr "È un cliente"
#~ msgid "Product Template"
#~ msgstr "Modello prodotto"
#~ msgid "Supplierinfo"
#~ msgstr "v"

View File

@@ -0,0 +1,33 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_customerinfo_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-09-11 12:45+0000\n"
"Last-Translator: Bosd <c5e2fd43-d292-4c90-9d1f-74ff3436329a@anonaddy.me>\n"
"Language-Team: none\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10.4\n"
#. module: product_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr "Prijzen voor klanten"
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr "Klantartikelcode"
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Verkooporderregel"

View File

@@ -0,0 +1,30 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_customerinfo_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \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_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr ""
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr ""
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,30 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_supplierinfo_for_customer_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.0\n"
"Report-Msgid-Bugs-To: \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_supplierinfo_for_customer_sale
#: model:ir.actions.act_window,name:product_supplierinfo_for_customer_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_supplierinfo_for_customer_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr ""
#. module: product_supplierinfo_for_customer_sale
#: model:ir.model.fields,field_description:product_supplierinfo_for_customer_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr ""
#. module: product_supplierinfo_for_customer_sale
#: model:ir.model,name:product_supplierinfo_for_customer_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,49 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_supplierinfo_for_customer_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2020-09-17 17:00+0000\n"
"Last-Translator: Pedro Castro Silva <pedrocs@exo.pt>\n"
"Language-Team: none\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 3.10\n"
#. module: product_customerinfo_sale
#: model:ir.actions.act_window,name:product_customerinfo_sale.action_open_product_customerinfo
#: model:ir.ui.menu,name:product_customerinfo_sale.menu_product_customerinfo
msgid "Prices for customers"
msgstr ""
#. module: product_customerinfo_sale
#: model:ir.model.fields,field_description:product_customerinfo_sale.field_sale_order_line__product_customer_code
msgid "Product Customer Code"
msgstr "Código do Produto no Cliente"
#. module: product_customerinfo_sale
#: model:ir.model,name:product_customerinfo_sale.model_sale_order_line
msgid "Sales Order Line"
msgstr "Linha de Encomenda de Venda"
#~ msgid ""
#~ "Check this box if this contact is a customer. It can be selected in sales "
#~ "orders."
#~ msgstr ""
#~ "Selecione esta caixa se o contacto for um cliente. Pode ser selecionado "
#~ "na encomendas de venda."
#~ msgid "Is a Customer"
#~ msgstr "É um Cliente"
#~ msgid "Product Template"
#~ msgstr "Modelo de Produto"
#~ msgid "Supplierinfo"
#~ msgstr "Info de Fornecedor"

View File

@@ -0,0 +1 @@
from . import sale_order_line

View File

@@ -0,0 +1,58 @@
# Copyright 2013-2017 Agile Business Group sagl
# (<http://www.agilebg.com>)
# Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com)
# Copyright 2024 Tecnativa - Víctor Martínez
# Copyright 2024 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
product_customer_code = fields.Char(
compute="_compute_product_customer_code",
)
@api.depends("product_id")
def _compute_product_customer_code(self):
for line in self:
if line.product_id:
supplierinfo = line.product_id._select_customerinfo(
partner=line.order_partner_id
)
code = supplierinfo.product_code
else:
code = ""
line.product_customer_code = code
def _compute_name(self):
"""We need to override the method with product_id is set so that the product
code is not added and add custom code of customerinfo."""
empty_lines = self.filtered(lambda x: not x.product_id)
super(SaleOrderLine, empty_lines)._compute_name()
for item in self - empty_lines:
customerinfo = item.product_id._select_customerinfo(
partner=item.order_partner_id
)
if customerinfo.product_code:
# Avoid to put the standard internal reference
item = item.with_context(display_default_code=False)
super(SaleOrderLine, item)._compute_name()
if customerinfo.product_code:
item.name = f"[{customerinfo.product_code}] {item.name}"
return
@api.onchange("product_id")
def _onchange_product_id_warning(self):
"""Assign the mininum quantity if set."""
res = super()._onchange_product_id_warning()
for line in self:
if line.product_id:
customerinfo = line.product_id._select_customerinfo(
partner=line.order_partner_id
)
if customerinfo.min_qty:
line.product_uom_qty = customerinfo.min_qty
return res

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,10 @@
- Xavier Jimenez \<<xavier.jimenez@qubiq.es>\>
- Nicola Malcontenti \<<nicola.malcontenti@agilebg.com>\>
- Serpent Consulting Services Pvt. Ltd. \<<support@serpentcs.com>\>
- Moisés López \<<moylop260@vauxoo.com>\>
- Yennifer Santiago \<<yennifer@vauxoo.com>\>
- Julio Serna Hernández \<<julio@vauxoo.com>\>
- Sergio Teruel \<<sergio.teruel@tecnativa.com>\>
- Lois Rilo \<<lois.rilo@forgeflow.com>\>
- Juany Davila \<<juany.davila@forgeflow.com>\>
- Carlos Reyes \<<carlos@studio73.es>\>

View File

@@ -0,0 +1,9 @@
Based on product_customerinfo, this module loads in every
sale order the customer code defined in the product and allows use the
product codes and product name configured in each products in sale
orders.
If you use Advanced price rules with formulas to define your pricing,
and choose that the price should be calculated from the partner prices
in the product form, the quantity in the sales order will be proposed
from the minimum quantity defined in the customerinfo.

View File

@@ -0,0 +1,2 @@
- Putting a minimum qty in a pricelist rule means the system will use
the option 'list price' instead of any option you chose.

View File

@@ -0,0 +1,22 @@
To use this module, you need:
- Go to product and configure *Partner product name* and *Partner
product code* for each selected customer.
![](../static/description/configuration_customer.png)
- When add order lines in sale quotation for a customer that has an
specific name and code in the product, you can search that product
with that customer name or code. Then, this values will be displayed
in product description.
![](../static/description/search_code.png)
![](../static/description/description_code.png)
- If product does not have a configuration for customer selected,
product will be search by its default code.
![](../static/description/search_code_2.png)
![](../static/description/description_code_2.png)

View File

@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_product_customerinfo_sale_manager,product.customerinfo.sale_manager,product_customerinfo.model_product_customerinfo,sales_team.group_sale_manager,1,1,1,1
access_product_customerinfo_sale_user,product.customerinfo.sale_user,product_customerinfo.model_product_customerinfo,sales_team.group_sale_salesman,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_product_customerinfo_sale_manager product.customerinfo.sale_manager product_customerinfo.model_product_customerinfo sales_team.group_sale_manager 1 1 1 1
3 access_product_customerinfo_sale_user product.customerinfo.sale_user product_customerinfo.model_product_customerinfo sales_team.group_sale_salesman 1 0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,471 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Product customer info sale</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="product-customer-info-sale">
<h1 class="title">Product customer info sale</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4d8f8f9641e008b30e802648977d0f2cef06d502d2558c62ef5ee64a1ee533fe
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sale-workflow/tree/18.0/product_customerinfo_sale"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-product_customerinfo_sale"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Based on product_customerinfo, this module loads in every sale order the
customer code defined in the product and allows use the product codes
and product name configured in each products in sale orders.</p>
<p>If you use Advanced price rules with formulas to define your pricing,
and choose that the price should be calculated from the partner prices
in the product form, the quantity in the sales order will be proposed
from the minimum quantity defined in the customerinfo.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>To use this module, you need:</p>
<ul class="simple">
<li>Go to product and configure <em>Partner product name</em> and <em>Partner
product code</em> for each selected customer.</li>
</ul>
<p><img alt="image1" src="https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/configuration_customer.png" /></p>
<ul class="simple">
<li>When add order lines in sale quotation for a customer that has an
specific name and code in the product, you can search that product
with that customer name or code. Then, this values will be displayed
in product description.</li>
</ul>
<p><img alt="image2" src="https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/search_code.png" /></p>
<p><img alt="image3" src="https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/description_code.png" /></p>
<ul class="simple">
<li>If product does not have a configuration for customer selected,
product will be search by its default code.</li>
</ul>
<p><img alt="image4" src="https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/search_code_2.png" /></p>
<p><img alt="image5" src="https://raw.githubusercontent.com/OCA/sale-workflow/18.0/product_customerinfo_sale/static/description/description_code_2.png" /></p>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Putting a minimum qty in a pricelist rule means the system will use
the option list price instead of any option you chose.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/sale-workflow/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/sale-workflow/issues/new?body=module:%20product_customerinfo_sale%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Agile Business Group</li>
<li>Vauxoo</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Xavier Jimenez &lt;<a class="reference external" href="mailto:xavier.jimenez&#64;qubiq.es">xavier.jimenez&#64;qubiq.es</a>&gt;</li>
<li>Nicola Malcontenti &lt;<a class="reference external" href="mailto:nicola.malcontenti&#64;agilebg.com">nicola.malcontenti&#64;agilebg.com</a>&gt;</li>
<li>Serpent Consulting Services Pvt. Ltd. &lt;<a class="reference external" href="mailto:support&#64;serpentcs.com">support&#64;serpentcs.com</a>&gt;</li>
<li>Moisés López &lt;<a class="reference external" href="mailto:moylop260&#64;vauxoo.com">moylop260&#64;vauxoo.com</a>&gt;</li>
<li>Yennifer Santiago &lt;<a class="reference external" href="mailto:yennifer&#64;vauxoo.com">yennifer&#64;vauxoo.com</a>&gt;</li>
<li>Julio Serna Hernández &lt;<a class="reference external" href="mailto:julio&#64;vauxoo.com">julio&#64;vauxoo.com</a>&gt;</li>
<li>Sergio Teruel &lt;<a class="reference external" href="mailto:sergio.teruel&#64;tecnativa.com">sergio.teruel&#64;tecnativa.com</a>&gt;</li>
<li>Lois Rilo &lt;<a class="reference external" href="mailto:lois.rilo&#64;forgeflow.com">lois.rilo&#64;forgeflow.com</a>&gt;</li>
<li>Juany Davila &lt;<a class="reference external" href="mailto:juany.davila&#64;forgeflow.com">juany.davila&#64;forgeflow.com</a>&gt;</li>
<li>Carlos Reyes &lt;<a class="reference external" href="mailto:carlos&#64;studio73.es">carlos&#64;studio73.es</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/sale-workflow/tree/18.0/product_customerinfo_sale">OCA/sale-workflow</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -0,0 +1 @@
from . import test_product_customerinfo_sale

View File

@@ -0,0 +1,169 @@
# Copyright 2017 ForgeFlow S.L.
# (http://www.forgeflow.com)
# Copyright 2024 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests import Form
from odoo.addons.base.tests.common import BaseCommon
class TestProductCustomerInfoSale(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.supplierinfo_model = cls.env["product.supplierinfo"]
cls.customerinfo_model = cls.env["product.customerinfo"]
cls.pricelist_item_model = cls.env["product.pricelist.item"]
cls.pricelist_model = cls.env["product.pricelist"]
cls.customer = cls._create_customer("customer1")
cls.product = cls.env.ref("product.product_product_4")
cls.product_variant_1 = cls.env.ref("product.product_product_4b")
cls.product_variant_2 = cls.env.ref("product.product_product_4c")
cls.customerinfo = cls._create_partnerinfo(
"customer", cls.customer, cls.product
)
cls.pricelist = cls._create_pricelist("Test Pricelist", cls.product)
cls.pricelist_item = cls._create_pricelist_item(
"Test Pricelist Item", cls.pricelist, cls.product
)
cls.company = cls.env.ref("base.main_company")
cls._create_partnerinfo("customer", cls.customer, cls.product_variant_1)
cls._create_partnerinfo(
"customer", cls.customer, cls.product_variant_2, empty_variant=True
)
cls.product_template = cls.env["product.template"].create(
{"name": "product wo variants"}
)
cls._create_partnerinfo(
"customer",
cls.customer,
cls.product_template.product_variant_ids[:1],
empty_variant=True,
)
cls.pricelist_template = cls._create_pricelist(
"Test Pricelist Template", cls.product_template.product_variant_ids[:1]
)
cls.env.user.groups_id |= cls.env.ref("product.group_product_pricelist")
@classmethod
def _create_customer(cls, name):
return cls.env["res.partner"].create(
{"name": name, "email": "example@yourcompany.com", "phone": 123456}
)
@classmethod
def _create_partnerinfo(
cls, supplierinfo_type, partner, product, empty_variant=False
):
vals = {
"partner_id": partner.id,
"product_id": product.id,
"product_name": "product4",
"product_code": "00001",
"price": 100.0,
"min_qty": 15.0,
}
if empty_variant:
vals.pop("product_id", None)
vals["product_tmpl_id"] = product.product_tmpl_id.id
return cls.env["product." + supplierinfo_type + "info"].create(vals)
@classmethod
def _create_pricelist(cls, name, product):
return cls.pricelist_model.create(
{"name": name, "currency_id": cls.env.ref("base.USD").id}
)
@classmethod
def _create_pricelist_item(cls, name, pricelist, product):
return cls.pricelist_item_model.create(
{
"name": name,
"pricelist_id": pricelist.id,
"applied_on": "0_product_variant",
"product_id": product.id,
"compute_price": "formula",
"base": "partner",
}
)
def test_product_customerinfo(self):
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.customer
order_form.pricelist_id = self.pricelist
with order_form.order_line.new() as line_form:
line_form.product_id = self.product
order = order_form.save()
line = order.order_line
self.assertIn("00001", order.order_line.name)
self.assertEqual(
line.product_customer_code,
self.customerinfo.product_code,
"Error: Customer product code was not passed to sale order line",
)
self.assertEqual(
line.product_uom_qty,
self.customerinfo.min_qty,
"Error: Min qty was not passed to the sale order line",
)
def test_product_customerinfo_variant(self):
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.customer
order_form.pricelist_id = self.pricelist
with order_form.order_line.new() as line_form:
line_form.product_id = self.product_variant_1
order = order_form.save()
line = order.order_line
self.assertEqual(
line.product_customer_code,
self.customerinfo.product_code,
"Error: Customer product code was not passed to sale order line",
)
def test_product_customerinfo_template(self):
customerinfo = self._create_partnerinfo(
"customer", self.customer, self.product_variant_2
)
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.customer
order_form.pricelist_id = self.pricelist
with order_form.order_line.new() as line_form:
line_form.product_id = self.product_variant_2
order = order_form.save()
line = order.order_line
self.assertEqual(
line.product_customer_code,
customerinfo.product_code,
"Error: Customer product code was not passed to sale order line",
)
# Test with product without variants
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.customer
order_form.pricelist_id = self.pricelist_template
with order_form.order_line.new() as line_form:
line_form.product_id = self.product_template.product_variant_ids[0]
order2 = order_form.save()
line2 = order2.order_line
self.assertEqual(
line2.product_customer_code,
customerinfo.product_code,
"Error: Customer product code was not passed to sale order line",
)
def test_product_customerinfo_variant_wo_template(self):
customerinfo = self._create_partnerinfo(
"customer", self.customer, self.product_variant_2, empty_variant=True
)
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.customer
order_form.pricelist_id = self.pricelist
with order_form.order_line.new() as line_form:
line_form.product_id = self.product_variant_2
order = order_form.save()
line = order.order_line
self.assertEqual(
line.product_customer_code,
customerinfo.product_code,
"Error: Customer product code was not passed to sale order line",
)

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright 2022 Tecnativa - Carlos Roca
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="action_open_product_customerinfo" model="ir.actions.act_window">
<field name="name">Prices for customers</field>
<field name="res_model">product.customerinfo</field>
<field name="context">{'visible_product_tmpl_id': False}</field>
<field name="view_mode">list,form</field>
</record>
<menuitem
id="menu_product_customerinfo"
action="action_open_product_customerinfo"
name="Prices for customers"
parent="sale.menu_sale_config"
sequence="1"
/>
</odoo>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
product customer code for OpenERP
Copyright (C) 2013 Agile Business Group sagl (<http://www.agilebg.com>).
Authors, Nicola Malcontenti, nicola.malcontenti@agilebg.com
Copyright (C) 2017 Vauxoo (https://www.vauxoo.com) info@vauxoo.com
Copyright 2021 ForgeFlow S.L. (https://www.forgeflow.com)
The licence is in the file __manifest__.py
-->
<odoo>
<record id="view_order_form" model="ir.ui.view">
<field name="name">sale.order.product.code.view.form</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="priority" eval="16" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='order_line']/list//field[@name='product_template_id']"
position="after"
>
<field name="product_customer_code" optional="show" />
</xpath>
<xpath
expr="//field[@name='order_line']/form//field[@name='product_id']"
position="after"
>
<field name="product_customer_code" />
</xpath>
</field>
</record>
</odoo>