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,110 @@
==================================
Sale Stock Line Customer Reference
==================================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:708a7e1b65e58df39f3722468a3278eadd89ebb888a7d7d805d857f4ed7b6140
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/sale_stock_line_customer_ref
: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-sale_stock_line_customer_ref
: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|
This module allows you to add a customer reference on a sale order line.
Lines sharing the same product but different customer references won't
be merged together in stock transfers.
**Table of contents**
.. contents::
:local:
Usage
=====
By default the customer reference field is not displayed on the sale
order form, you have to enable it in the list of optional fields.
We want the customer ref on the package because the label should be
printed from there (like all other kind of existing labels). As we can't
get the right stock.move.line/stock.move easily from the package it is
easier to store the Customer Ref. of the move/move_line on the package
when this one is assigned to the move line. Also, a (destination)
package could contain different products (so different moves), and these
moves could have different Customer Ref., all of them will be concatened
in the package => ",
".join(customer_ref_of_all_moves_link_to_this_package)
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-workflow/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_stock_line_customer_ref%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
-------
* Camptocamp
Contributors
------------
- Sébastien Alix <sebastien.alix@camptocamp.com>
- Simone Orsi <simone.orsi@camptocamp.com>
- Do Anh Duy <duyda@trobz.com>
Other credits
-------------
The migration of this module from 14.0 to 18.0 was financially supported
by Camptocamp.
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.
.. |maintainer-sebalix| image:: https://github.com/sebalix.png?size=40px
:target: https://github.com/sebalix
:alt: sebalix
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-sebalix|
This module is part of the `OCA/sale-workflow <https://github.com/OCA/sale-workflow/tree/18.0/sale_stock_line_customer_ref>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,2 @@
from . import models
from .hooks import pre_init_hook

View File

@@ -0,0 +1,28 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
{
"name": "Sale Stock Line Customer Reference",
"summary": (
"Allow you to add a customer reference on order lines "
"propagaged to move operations."
),
"version": "18.0.1.0.0",
"author": "Camptocamp, Odoo Community Association (OCA)",
"maintainers": ["sebalix"],
"website": "https://github.com/OCA/sale-workflow",
"category": "Sales/Sales",
"depends": ["sale_stock"],
"data": [
"views/sale_order.xml",
"views/stock_picking.xml",
"views/stock_move.xml",
"views/stock_move_line.xml",
"views/stock_package_level.xml",
"views/stock_quant_package.xml",
],
"license": "AGPL-3",
"installable": True,
"application": False,
"development_status": "Beta",
"pre_init_hook": "pre_init_hook",
}

View File

@@ -0,0 +1,34 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import logging
from odoo.tools import sql
logger = logging.getLogger(__name__)
def pre_init_hook(env):
"""Create table columns for computed fields to not get them computed by Odoo.
This is done to avoid MemoryError when installing the module on big databases.
Also it is useless to compute these fields which should be empty when installing
the module because no SO lines have a customer reference set.
"""
# Create columns
cr = env.cr
if not sql.column_exists(cr, "stock_move", "customer_ref_sale_line_id"):
sql.create_column(
cr,
"stock_move",
"customer_ref_sale_line_id",
"int4",
comment="Sale Line With Customer Ref",
)
if not sql.column_exists(cr, "stock_move", "customer_ref"):
sql.create_column(
cr,
"stock_move",
"customer_ref",
"VARCHAR",
)

View File

@@ -0,0 +1,97 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_stock_line_customer_ref
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-01-28 13:33+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.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: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move_line__customer_ref
msgid "Customer Ref"
msgstr "Ref. del Cliente"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_sale_order_line__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer Ref."
msgstr "Ref. del Cliente."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer reference coming from the sale order line."
msgstr "Referencia del cliente procedente de la línea de pedidos de venta."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Has Customer Ref"
msgstr "Tiene Ref de Cliente"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_quant_package
msgid "Packages"
msgstr "Paquetes"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move_line
msgid "Product Moves (Stock Move Line)"
msgstr "Movimientos de Producto (Línea de Movimiento de Existencias)"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref_sale_line_id
msgid "Sale Line With Customer Ref."
msgstr "Línea de Venta Con Ref. Cliente."
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_sale_order_line
msgid "Sales Order Line"
msgstr "Línea de Orden de Venta"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move
msgid "Stock Move"
msgstr "Movimiento de Existencias"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_package_level
msgid "Stock Package Level"
msgstr "Nivel del Paquete de Existencias"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
msgid "Technical field to display 'Customer Ref' column in a package level."
msgstr ""
"Paquete de Existencias Campo técnico para mostrar la columna 'Ref. cliente' "
"en un nivel de paquete."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Technical field to display 'Customer Ref' column on moves."
msgstr ""
"Campo técnico para mostrar la columna \" Ref cliente \" en los movimientos."
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_picking
msgid "Transfer"
msgstr "Transferencia"
#~ msgid "Display Name"
#~ msgstr "Mostrar Nombre"
#~ msgid "ID"
#~ msgstr "ID"
#~ msgid "Last Modified on"
#~ msgstr "Última Modificación el"

View File

@@ -0,0 +1,86 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_stock_line_customer_ref
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-02-27 11:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\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.6.2\n"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move_line__customer_ref
msgid "Customer Ref"
msgstr "Rif. cliente"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_sale_order_line__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer Ref."
msgstr "Rif. cliente"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer reference coming from the sale order line."
msgstr "Riferimento cliente che viene dalla riga ordine di vendita."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Has Customer Ref"
msgstr "Ha riferimento cliente"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_quant_package
msgid "Packages"
msgstr "Colli"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move_line
msgid "Product Moves (Stock Move Line)"
msgstr "Movimenti prodotto (riga movimento di magazzino)"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref_sale_line_id
msgid "Sale Line With Customer Ref."
msgstr "Riga vendita con rif. cliente"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_sale_order_line
msgid "Sales Order Line"
msgstr "Riga ordine di vendita"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move
msgid "Stock Move"
msgstr "Movimento di magazzino"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_package_level
msgid "Stock Package Level"
msgstr "Livello collo magazzino"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
msgid "Technical field to display 'Customer Ref' column in a package level."
msgstr ""
"Campo tecnico per visualizzare la colonna 'Rif. cliente' in un livello collo."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Technical field to display 'Customer Ref' column on moves."
msgstr "Campo tecnico per visualizzare la colonna 'Rif. cliente' nei movimenti."
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_picking
msgid "Transfer"
msgstr "Trasferimento"

View File

@@ -0,0 +1,86 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_stock_line_customer_ref
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-04-13 12:24+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: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move_line__customer_ref
msgid "Customer Ref"
msgstr "Klantreferentie"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_sale_order_line__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer Ref."
msgstr "Klantref."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer reference coming from the sale order line."
msgstr "Klantreferentie afkomstig van de verkooporderregel."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Has Customer Ref"
msgstr "Heeft Klantref"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_quant_package
msgid "Packages"
msgstr "Pakketten"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move_line
msgid "Product Moves (Stock Move Line)"
msgstr "Productbewegingen (Voorraadmutatieregel)"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref_sale_line_id
msgid "Sale Line With Customer Ref."
msgstr "Verkoopregel met Klantref."
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_sale_order_line
msgid "Sales Order Line"
msgstr "Verkooporderregel"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move
msgid "Stock Move"
msgstr "Voorraadmutatie"
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_package_level
msgid "Stock Package Level"
msgstr "Voorraadpakketniveau"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
msgid "Technical field to display 'Customer Ref' column in a package level."
msgstr ""
"Technisch veld om de kolom 'Klantref' weer te geven op een pakketniveau."
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Technical field to display 'Customer Ref' column on moves."
msgstr "Technisch veld om de kolom 'Klantref' weer te geven bij mutaties."
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_picking
msgid "Transfer"
msgstr "Overdracht"

View File

@@ -0,0 +1,83 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_stock_line_customer_ref
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: Automatically generated\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"
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move_line__customer_ref
msgid "Customer Ref"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_sale_order_line__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer Ref."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer reference coming from the sale order line."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Has Customer Ref"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_quant_package
msgid "Packages"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move_line
msgid "Product Moves (Stock Move Line)"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref_sale_line_id
msgid "Sale Line With Customer Ref."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move
msgid "Stock Move"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_package_level
msgid "Stock Package Level"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
msgid "Technical field to display 'Customer Ref' column in a package level."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Technical field to display 'Customer Ref' column on moves."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_picking
msgid "Transfer"
msgstr ""

View File

@@ -0,0 +1,82 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_stock_line_customer_ref
#
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: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move_line__customer_ref
msgid "Customer Ref"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_sale_order_line__customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer Ref."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_quant_package__customer_ref
msgid "Customer reference coming from the sale order line."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Has Customer Ref"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_quant_package
msgid "Packages"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move_line
msgid "Product Moves (Stock Move Line)"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,field_description:sale_stock_line_customer_ref.field_stock_move__customer_ref_sale_line_id
msgid "Sale Line With Customer Ref."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_sale_order_line
msgid "Sales Order Line"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_move
msgid "Stock Move"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_package_level
msgid "Stock Package Level"
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_package_level__has_customer_ref
msgid "Technical field to display 'Customer Ref' column in a package level."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model.fields,help:sale_stock_line_customer_ref.field_stock_picking__has_customer_ref
msgid "Technical field to display 'Customer Ref' column on moves."
msgstr ""
#. module: sale_stock_line_customer_ref
#: model:ir.model,name:sale_stock_line_customer_ref.model_stock_picking
msgid "Transfer"
msgstr ""

View File

@@ -0,0 +1,6 @@
from . import sale_order_line
from . import stock_move
from . import stock_move_line
from . import stock_package_level
from . import stock_picking
from . import stock_quant_package

View File

@@ -0,0 +1,15 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo import fields, models
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
customer_ref = fields.Char(string="Customer Ref.")
def _prepare_procurement_values(self, group_id=False):
values = super()._prepare_procurement_values(group_id)
values["customer_ref"] = self.customer_ref
return values

View File

@@ -0,0 +1,62 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo import api, fields, models
class StockMove(models.Model):
_inherit = "stock.move"
customer_ref_sale_line_id = fields.Many2one(
comodel_name="sale.order.line",
compute="_compute_customer_ref_sale_line_id",
string="Sale Line With Customer Ref.",
store=True,
index=True,
)
customer_ref = fields.Char(compute="_compute_customer_ref", store=True)
@api.depends("sale_line_id.customer_ref", "move_dest_ids.sale_line_id")
def _compute_customer_ref_sale_line_id(self):
for move in self:
sale_line = move._get_customer_ref_sale_line()
move.customer_ref_sale_line_id = sale_line
@api.depends("customer_ref_sale_line_id.customer_ref")
def _compute_customer_ref(self):
for move in self:
move.customer_ref = move.customer_ref_sale_line_id.customer_ref
def _get_customer_ref_sale_line(self):
"""Return the SO line with a customer ref. from the ship move."""
self.ensure_one()
if self.sale_line_id.customer_ref:
return self.sale_line_id
if not self.move_dest_ids:
return self.sale_line_id.browse()
# Search in the destination moves recursively until we find a SO line
moves_dest = self.move_dest_ids
move_seen_ids = set(moves_dest.ids)
while moves_dest:
for move_dest in moves_dest:
# As soon as the SO line has a customer reference, we break.
# That means for pick+pack moves we return the first SO line found.
if move_dest.sale_line_id.customer_ref:
return move_dest.sale_line_id
# Guard to avoid infinite loop. This should not happen.
recursion_move_ids = move_seen_ids & set(moves_dest.move_dest_ids.ids)
if recursion_move_ids:
break
moves_dest = moves_dest.move_dest_ids
move_seen_ids |= set(moves_dest.ids)
return self.sale_line_id.browse()
@api.model
def _prepare_merge_moves_distinct_fields(self):
distinct_fields = super()._prepare_merge_moves_distinct_fields()
# While ship moves can't be merged together as they are coming from
# different SO lines ('sale_line_id' is part of the merge-key in
# 'sale_stock'), we allow only the merge of chained moves like
# pick+pack based on the customer reference.
distinct_fields.append("customer_ref")
return distinct_fields

View File

@@ -0,0 +1,48 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from contextlib import contextmanager
from odoo import fields, models
class StockMoveLine(models.Model):
_inherit = "stock.move.line"
customer_ref = fields.Char(related="move_id.customer_ref")
def write(self, vals):
# Overridden to update related result packages
with self.update_related_packages(vals):
res = super().write(vals)
return res
@contextmanager
def update_related_packages(self, vals):
"""Keep packages in sync."""
# FIXME: is not granted that all the lines involved
# by the pkg will be updated here.
# We should look for all lines linked to the same picking and update them all.
result_package_updated = "result_package_id" in vals
if result_package_updated:
old_packages = self.result_package_id
yield
if result_package_updated:
self._update_related_packages(old_packages)
def _update_related_packages(self, old_packages):
# Remove Customer Ref. from packages that are used anymore
new_package = self.result_package_id
(old_packages - new_package).write(self._update_related_old_pkg_vals())
# Collect all Customer Ref. from lines and store them in the package
new_package.write(self._update_related_new_pkg_vals())
def _update_related_old_pkg_vals(self):
return {"customer_ref": False}
def _update_related_new_pkg_vals(self):
return {
"customer_ref": ", ".join(
sorted({x.customer_ref for x in self if x.customer_ref})
)
}

View File

@@ -0,0 +1,21 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo import api, fields, models
class StockPackageLevel(models.Model):
_inherit = "stock.package_level"
has_customer_ref = fields.Boolean(
compute="_compute_has_customer_ref",
help="Technical field to display 'Customer Ref' column in a package level.",
)
@api.depends("move_ids.customer_ref")
def _compute_has_customer_ref(self):
for pl in self:
# Break on the first move or line having a customer ref
pl.has_customer_ref = next(
(move for move in pl.move_ids if move.customer_ref), False
) or next((line for line in pl.move_line_ids if line.customer_ref), False)

View File

@@ -0,0 +1,33 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo import api, fields, models
class StockPicking(models.Model):
_inherit = "stock.picking"
has_customer_ref = fields.Boolean(
compute="_compute_has_customer_ref",
help="Technical field to display 'Customer Ref' column on moves.",
)
@api.depends("move_ids.customer_ref")
def _compute_has_customer_ref(self):
for picking in self:
# Break on the first move having a customer ref
picking.has_customer_ref = next(
(
move
for move in picking.move_ids_without_package
if move.customer_ref
),
False,
)
def action_detailed_operations(self):
res = super().action_detailed_operations()
ctx = dict(res.get("context", {}))
ctx["has_customer_ref"] = self.has_customer_ref
res["context"] = ctx
return res

View File

@@ -0,0 +1,13 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from odoo import fields, models
class StockQuantPackage(models.Model):
_inherit = "stock.quant.package"
customer_ref = fields.Char(
string="Customer Ref.",
help="Customer reference coming from the sale order line.",
)

View File

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

View File

@@ -0,0 +1,3 @@
- Sébastien Alix \<<sebastien.alix@camptocamp.com>\>
- Simone Orsi \<<simone.orsi@camptocamp.com>\>
- Do Anh Duy \<<duyda@trobz.com>\>

View File

@@ -0,0 +1 @@
The migration of this module from 14.0 to 18.0 was financially supported by Camptocamp.

View File

@@ -0,0 +1,3 @@
This module allows you to add a customer reference on a sale order line.
Lines sharing the same product but different customer references won't
be merged together in stock transfers.

View File

@@ -0,0 +1,6 @@
By default the customer reference field is not displayed on the sale
order form, you have to enable it in the list of optional fields.
We want the customer ref on the package because the label should be printed from there (like all other kind of existing labels).
As we can't get the right stock.move.line/stock.move easily from the package it is easier to store the Customer Ref. of the move/move_line on the package when this one is assigned to the move line.
Also, a (destination) package could contain different products (so different moves), and these moves could have different Customer Ref., all of them will be concatened in the package => ", ".join(customer_ref_of_all_moves_link_to_this_package)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,450 @@
<!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>Sale Stock Line Customer Reference</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="sale-stock-line-customer-reference">
<h1 class="title">Sale Stock Line Customer Reference</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:708a7e1b65e58df39f3722468a3278eadd89ebb888a7d7d805d857f4ed7b6140
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/sale_stock_line_customer_ref"><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-sale_stock_line_customer_ref"><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>This module allows you to add a customer reference on a sale order line.
Lines sharing the same product but different customer references wont
be merged together in stock transfers.</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="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-6">Other credits</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>By default the customer reference field is not displayed on the sale
order form, you have to enable it in the list of optional fields.</p>
<p>We want the customer ref on the package because the label should be
printed from there (like all other kind of existing labels). As we cant
get the right stock.move.line/stock.move easily from the package it is
easier to store the Customer Ref. of the move/move_line on the package
when this one is assigned to the move line. Also, a (destination)
package could contain different products (so different moves), and these
moves could have different Customer Ref., all of them will be concatened
in the package =&gt; “,
“.join(customer_ref_of_all_moves_link_to_this_package)</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">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:%20sale_stock_line_customer_ref%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-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<ul class="simple">
<li>Sébastien Alix &lt;<a class="reference external" href="mailto:sebastien.alix&#64;camptocamp.com">sebastien.alix&#64;camptocamp.com</a>&gt;</li>
<li>Simone Orsi &lt;<a class="reference external" href="mailto:simone.orsi&#64;camptocamp.com">simone.orsi&#64;camptocamp.com</a>&gt;</li>
<li>Do Anh Duy &lt;<a class="reference external" href="mailto:duyda&#64;trobz.com">duyda&#64;trobz.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
<h2><a class="toc-backref" href="#toc-entry-6">Other credits</a></h2>
<p>The migration of this module from 14.0 to 18.0 was financially supported
by Camptocamp.</p>
</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>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/sebalix"><img alt="sebalix" src="https://github.com/sebalix.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/sale-workflow/tree/18.0/sale_stock_line_customer_ref">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>

View File

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

View File

@@ -0,0 +1,133 @@
# Copyright 2022 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo.tests import Form
from odoo.addons.base.tests.common import BaseCommon
class TestSaleLineCustomerRef(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.wh = cls.env.ref("stock.warehouse0")
cls.wh.delivery_steps = "pick_pack_ship"
cls.product = cls.env.ref("product.consu_delivery_01")
delivery_route = cls.wh.delivery_route_id
rule_id1 = delivery_route.rule_ids[1]
delivery_route.rule_ids[0].location_dest_id = rule_id1.location_src_id.id
delivery_route.rule_ids.write({"action": "pull"})
cls.stock_loc = cls.wh.lot_stock_id
cls.order = cls._create_order()
cls.order.action_confirm()
cls.pkg_model = cls.env["stock.quant.package"]
@classmethod
def _create_order(cls):
# Create a SO with 4 lines sharing the same product but with 2 different
# customer references.
with Form(cls.env["sale.order"]) as form:
form.partner_id = cls.env.ref("base.res_partner_1")
for i in range(4):
with form.order_line.new() as line:
line.product_id = cls.product
line.customer_ref = f"TEST_{i % 2}"
line.product_uom = cls.product.uom_id
line.product_uom_qty = 1
order = form.save()
return order
@classmethod
def _update_qty_in_location(
cls, location, product, quantity, package=None, lot=None
):
quants = cls.env["stock.quant"]._gather(
product, location, lot_id=lot, package_id=package, strict=True
)
# this method adds the quantity to the current quantity, so remove it
quantity -= sum(quants.mapped("quantity"))
cls.env["stock.quant"]._update_available_quantity(
product, location, quantity, package_id=package, lot_id=lot
)
@classmethod
def _get_pick(cls, order):
return order.picking_ids.filtered(lambda x: not x.move_ids.move_orig_ids)
@classmethod
def _get_pack(cls, order):
return cls._get_pick(order).move_ids.move_dest_ids.picking_id
def test_customer_ref(self):
# Ship moves can't be merged anyway in std Odoo as they belong to
# different SO lines, but chained moves not linked directly to
# the SO lines can still be merged based on the customer reference.
self.assertEqual(len(self.order.order_line), 4)
self.assertEqual(len(self.order.order_line.move_ids), 4)
self._test_customer_ref()
def _test_customer_ref(self):
# Check customer ref. among chained moves of all SO lines
for i in range(4):
expected_ref = f"TEST_{i % 2}"
order_line = self.order.order_line[i]
order_lines_same_ref = self.order.order_line.filtered_domain(
[("customer_ref", "=", expected_ref)]
)
self.assertEqual(order_line.customer_ref, expected_ref)
# Customer reference is propagated on the ship move
move_ship = order_line.move_ids
self.assertEqual(move_ship.customer_ref_sale_line_id, order_line)
self.assertEqual(move_ship.customer_ref, expected_ref)
self.assertEqual(move_ship.product_uom_qty, 1)
# And on the pack and pick moves have been merged based on
# the propagated customer reference.
move_pack = move_ship.move_orig_ids
self.assertIn(move_pack.customer_ref_sale_line_id, order_lines_same_ref)
self.assertEqual(move_pack.customer_ref, expected_ref)
self.assertEqual(move_pack.product_uom_qty, 2)
move_pick = move_pack.move_orig_ids
self.assertIn(move_pick.customer_ref_sale_line_id, order_lines_same_ref)
self.assertEqual(move_pick.customer_ref, expected_ref)
self.assertEqual(move_pick.product_uom_qty, 2)
def test_has_customer_ref(self):
for picking in self.order.picking_ids:
self.assertTrue(picking.has_customer_ref)
def test_package_ref(self):
self._update_qty_in_location(self.stock_loc, self.product, 10)
picking = self._get_pick(self.order)
picking.action_assign()
expected = ["TEST_0", "TEST_1"]
self.assertEqual(picking.move_line_ids.mapped("customer_ref"), expected)
pkg1 = self.pkg_model.create({"name": "TEST-REF-1"})
pkg2 = self.pkg_model.create({"name": "TEST-REF-2"})
picking.move_line_ids[0].result_package_id = pkg1
picking.move_line_ids[1].result_package_id = pkg2
packages = picking.move_line_ids.result_package_id.sorted("name")
packages.invalidate_recordset()
self.assertEqual(packages.mapped("customer_ref"), ["TEST_0", "TEST_1"])
picking.move_line_ids.filtered(
lambda x: x.result_package_id == pkg2
).result_package_id = False
packages.invalidate_recordset()
self.assertEqual(packages.mapped("customer_ref"), ["TEST_0", False])
def test_package_ref_concat(self):
self._update_qty_in_location(self.stock_loc, self.product, 10)
picking = self._get_pick(self.order)
picking.action_assign()
expected = ["TEST_0", "TEST_1"]
self.assertEqual(picking.move_line_ids.mapped("customer_ref"), expected)
pkg1 = self.pkg_model.create({"name": "TEST-REF-1"})
self.pkg_model.create({"name": "TEST-REF-2"})
picking.move_line_ids.result_package_id = pkg1
packages = picking.move_line_ids.result_package_id.sorted("name")
packages.invalidate_recordset()
self.assertEqual(packages.mapped("customer_ref"), ["TEST_0, TEST_1"])
picking.move_line_ids.result_package_id = False
packages.invalidate_recordset()
self.assertEqual(packages.mapped("customer_ref"), [False])

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2022 Camptocamp SA
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_order_form" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='order_line']/list/field[@name='name']"
position="after"
>
<field name="customer_ref" optional="hide" />
</xpath>
<xpath
expr="//field[@name='order_line']/form//field[@name='analytic_distribution']"
position="after"
>
<field name="customer_ref" />
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2022 Camptocamp SA
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_stock_move_operations" model="ir.ui.view">
<field name="name">stock.move.operations.form.inherit</field>
<field name="model">stock.move</field>
<field name="inherit_id" ref="stock.view_stock_move_operations" />
<field name="arch" type="xml">
<field name="product_id" position="after">
<field name="customer_ref" invisible="not customer_ref" />
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2022 Camptocamp SA
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_move_line_form" model="ir.ui.view">
<field name="name">stock.move.line.form.inherit</field>
<field name="model">stock.move.line</field>
<field name="inherit_id" ref="stock.view_move_line_form" />
<field name="arch" type="xml">
<field name="product_id" position="after">
<field name="customer_ref" invisible="not customer_ref" />
</field>
</field>
</record>
<record id="view_stock_move_line_detailed_operation_tree" model="ir.ui.view">
<field name="name">stock.move.line.operations.list.inherit</field>
<field name="model">stock.move.line</field>
<field
name="inherit_id"
ref="stock.view_stock_move_line_detailed_operation_tree"
/>
<field name="arch" type="xml">
<field name="product_id" position="after">
<field
name="customer_ref"
column_invisible="not context.get('has_customer_ref')"
/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2022 Camptocamp SA
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="package_level_form_view" model="ir.ui.view">
<field name="name">stock.package_level.form.inherit</field>
<field name="model">stock.package_level</field>
<field name="inherit_id" ref="stock.package_level_form_view" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='move_ids']/list/field[@name='product_id']"
position="after"
>
<field
name="customer_ref"
column_invisible="not parent.has_customer_ref"
/>
</xpath>
<xpath
expr="//field[@name='move_line_ids']/list/field[@name='product_id']"
position="after"
>
<field
name="customer_ref"
column_invisible="not parent.has_customer_ref"
/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2022 Camptocamp SA
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_picking_form" model="ir.ui.view">
<field name="name">stock.picking.form.inherit</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form" />
<field name="arch" type="xml">
<xpath
expr="//field[@name='move_ids_without_package']/list/field[@name='product_id']"
position="after"
>
<field
name="customer_ref"
column_invisible="not parent.has_customer_ref"
/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2023 Camptocamp SA
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_quant_package_form" model="ir.ui.view">
<field name="name">stock.quant.package.form.inherit</field>
<field name="model">stock.quant.package</field>
<field name="inherit_id" ref="stock.view_quant_package_form" />
<field name="arch" type="xml">
<xpath
expr="//form/sheet/group/group/field[@name='location_id']"
position="after"
>
<field name="customer_ref" />
</xpath>
</field>
</record>
</odoo>