Merge PR #1300 into 15.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2024-11-12 08:52:36 +00:00
26 changed files with 1461 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
=========================
Purchase MRP Distribution
=========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:51d9b4cab80068fcea738841c68a570388273d7cde664d9603cad40b83184c13
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fmanufacture-lightgray.png?logo=github
:target: https://github.com/OCA/manufacture/tree/15.0/purchase_mrp_distribution
:alt: OCA/manufacture
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/manufacture-15-0/manufacture-15-0-purchase_mrp_distribution
: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/manufacture&target_branch=15.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows you to buy a product that will be divided into others without
knowing the exact quantity of the others. That quantity will be filled in the picking.
**Table of contents**
.. contents::
:local:
Configuration
=============
To use this module, we will need to configure n different distribution-type Bills of
Materials (BoM) for n products. To do this, we will follow these steps:
#. Go to Manufacturing > Products > Bills of Materials
#. Click on Create
#. Select the product to be distributed in the receptions
#. Select the BoM type "Distribution"
#. In the components, add the products that can be filled in the reception (it is not
necessary to mark the quantity as it will default to 0)
Usage
=====
To see the module's functionality:
1. Create a new purchase order
2. Add the product for which the BoM has been created
3. Confirm the order
4. Go to the created delivery order
5. You will see a new button in the move that contains the product, click on it
6. A wizard will open to define the quantity of each product to distribute
7. By clicking on Distribute, the move lines will be added with the products from the
BoM
Known issues / Roadmap
======================
#. The current module is not designed to handle multi-step receipts. It operates on a
single-step process, making it unsuitable for more complex inventory management
scenarios.
#. The current module is not designed to handle multiple lots for a product.
#. The current module is not designed to handle multiple packages for a product.
Changelog
=========
This module aims to address the need to receive a generic product, but until the
moment of reception, we do not know the quantity that we might receive of its
specific products.
Using kits was not suitable for us, because to account for a unit of the kit product,
the quantity specified in the BoM must be received. Therefore, we opted to define a
new type of BoM called distribution.
In this way, upon receiving a unit of any product added to the BoM, it will be
accounted for as a unit of the generic product and will be reflected in the svls as
separate products, but they will be accounted for in the purchase line as part of the
product.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/manufacture/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/manufacture/issues/new?body=module:%20purchase_mrp_distribution%0Aversion:%2015.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
~~~~~~~
* Tecnaiva
Contributors
~~~~~~~~~~~~
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Carlos Roca
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/manufacture <https://github.com/OCA/manufacture/tree/15.0/purchase_mrp_distribution>`_ 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 . import wizards

View File

@@ -0,0 +1,20 @@
# Copyright 2024 Tecnatva - Carlos Roca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Purchase MRP Distribution",
"version": "15.0.1.0.0",
"author": "Tecnaiva, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/manufacture",
"category": "Manufacturing",
"depends": ["purchase_mrp"],
"data": [
"security/ir.model.access.csv",
"views/mrp_bom_views.xml",
"views/stock_picking_views.xml",
"wizards/stock_move_distribution_wiz_views.xml",
],
"license": "AGPL-3",
"installable": True,
"application": False,
}

View File

@@ -0,0 +1,189 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * purchase_mrp_distribution
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-09 09:38+0000\n"
"PO-Revision-Date: 2024-07-09 11:50+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.purchase_order_form
msgid ""
"A BoM of type distribution is used to select the quantities of components."
msgstr ""
"Una lista de materiales (BoM) de tipo distribución se utiliza para "
"seleccionar las cantidades de componentes."
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.purchase_order_form
msgid "At a Stock Transfer."
msgstr "En una transferencia de stock."
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_mrp_bom
msgid "Bill of Material"
msgstr "Lista de material"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_mrp_bom__type
msgid "BoM Type"
msgstr "Tipo de LdM"
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.stock_move_distribution_wiz_form
msgid "Cancel"
msgstr "Cancelar"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__create_uid
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__create_date
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__create_date
msgid "Created on"
msgstr "Creado el"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__demand_quantity
msgid "Demand"
msgstr "Demanda"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__display_name
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__display_name
msgid "Display Name"
msgstr "Nombre a mostrar"
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.stock_move_distribution_wiz_form
msgid "Distribute"
msgstr "Distribuir"
#. module: purchase_mrp_distribution
#: model:ir.model.fields.selection,name:purchase_mrp_distribution.selection__mrp_bom__type__distribution
msgid "Distribution"
msgstr "Distribución"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move__distribution_bom_id
msgid "Distribution Bom"
msgstr "LdM de distribución"
#. module: purchase_mrp_distribution
#: code:addons/purchase_mrp_distribution/models/stock_move.py:0
#, python-format
msgid "Distribution for %s"
msgstr "Distribución para %s"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__id
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__id
msgid "ID"
msgstr "ID"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz____last_update
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line____last_update
msgid "Last Modified on"
msgstr "Última modificación el"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__write_uid
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__write_date
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__write_date
msgid "Last Updated on"
msgstr "Última actualización el"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__line_ids
msgid "Line"
msgstr "Linea"
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_stock_move_distribution_wiz_line
msgid "Lines of wizard to distribute product qty to diferent products"
msgstr ""
"Líneas del asistente para distribuir la cantidad del producto a diferentes "
"productos"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__move_id
msgid "Move"
msgstr "Movimiento"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__product_id
msgid "Product"
msgstr "Producto"
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_purchase_order_line
msgid "Purchase Order Line"
msgstr "Línea de pedido de venta"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__quantity
msgid "Quantity"
msgstr "Cantidad"
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_stock_move
msgid "Stock Move"
msgstr "Movimiento de Stock"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,help:purchase_mrp_distribution.field_stock_move_distribution_wiz__demand_quantity
msgid ""
"This is the quantity of products from an inventory point of view. For moves "
"in the state 'done', this is the quantity of products that were actually "
"moved. For other moves, this is the quantity of product that is planned to "
"be moved. Lowering this quantity does not generate a backorder. Changing "
"this quantity on assigned moves affects the product reservation, and should "
"be done with care."
msgstr ""
"Ésta es la cantidad de productos desde un punto de vista de inventario. "
"Para movimientos en el estado 'Realizado', ésta es la cantidad de productos "
"que se movieron realmente. Para otros movimientos, ésta es la cantidad de "
"producto que está planeado mover. Disminuyendo esta cantidad no se genera "
"un pedido en espera. Cambiando esta cantidad en movimientos asignados, "
"afecta la reserva de producto, y debe ser realizado con cuidado."
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__move_uom_id
msgid "UoM"
msgstr "UdM"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__uom_id
msgid "Uom"
msgstr "UdM"
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__wizard_id
msgid "Wizard"
msgstr "Asistente"
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_stock_move_distribution_wiz
msgid "Wizard to distribute product qty to diferent products"
msgstr ""
"Asistente para distribuir la cantidad de producto a diferentes productos"

View File

@@ -0,0 +1,176 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * purchase_mrp_distribution
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-09 09:38+0000\n"
"PO-Revision-Date: 2024-07-09 09:38+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.purchase_order_form
msgid ""
"A BoM of type distribution is used to select the quantities of components."
msgstr ""
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.purchase_order_form
msgid "At a Stock Transfer."
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_mrp_bom
msgid "Bill of Material"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_mrp_bom__type
msgid "BoM Type"
msgstr ""
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.stock_move_distribution_wiz_form
msgid "Cancel"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__create_uid
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__create_uid
msgid "Created by"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__create_date
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__create_date
msgid "Created on"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__demand_quantity
msgid "Demand"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__display_name
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__display_name
msgid "Display Name"
msgstr ""
#. module: purchase_mrp_distribution
#: model_terms:ir.ui.view,arch_db:purchase_mrp_distribution.stock_move_distribution_wiz_form
msgid "Distribute"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields.selection,name:purchase_mrp_distribution.selection__mrp_bom__type__distribution
msgid "Distribution"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move__distribution_bom_id
msgid "Distribution Bom"
msgstr ""
#. module: purchase_mrp_distribution
#: code:addons/purchase_mrp_distribution/models/stock_move.py:0
#, python-format
msgid "Distribution for %s"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__id
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__id
msgid "ID"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz____last_update
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line____last_update
msgid "Last Modified on"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__write_uid
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__write_uid
msgid "Last Updated by"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__write_date
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__write_date
msgid "Last Updated on"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__line_ids
msgid "Line"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_stock_move_distribution_wiz_line
msgid "Lines of wizard to distribute product qty to diferent products"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__move_id
msgid "Move"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__product_id
msgid "Product"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_purchase_order_line
msgid "Purchase Order Line"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__quantity
msgid "Quantity"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_stock_move
msgid "Stock Move"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,help:purchase_mrp_distribution.field_stock_move_distribution_wiz__demand_quantity
msgid ""
"This is the quantity of products from an inventory point of view. For moves "
"in the state 'done', this is the quantity of products that were actually "
"moved. For other moves, this is the quantity of product that is planned to "
"be moved. Lowering this quantity does not generate a backorder. Changing "
"this quantity on assigned moves affects the product reservation, and should "
"be done with care."
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz__move_uom_id
msgid "UoM"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__uom_id
msgid "Uom"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model.fields,field_description:purchase_mrp_distribution.field_stock_move_distribution_wiz_line__wizard_id
msgid "Wizard"
msgstr ""
#. module: purchase_mrp_distribution
#: model:ir.model,name:purchase_mrp_distribution.model_stock_move_distribution_wiz
msgid "Wizard to distribute product qty to diferent products"
msgstr ""

View File

@@ -0,0 +1,3 @@
from . import mrp_bom
from . import purchase
from . import stock_move

View File

@@ -0,0 +1,13 @@
# Copyright 2024 Tecnativa - Carlos Roca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class MrpBom(models.Model):
_inherit = "mrp.bom"
type = fields.Selection(
selection_add=[("distribution", "Distribution")],
ondelete={"distribution": "set default"},
)

View File

@@ -0,0 +1,39 @@
# Copyright 2024 Tecnativa - Carlos Roca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models
class PurchaseOrderLine(models.Model):
_inherit = "purchase.order.line"
def _prepare_stock_move_vals(
self, picking, price_unit, product_uom_qty, product_uom
):
res = super()._prepare_stock_move_vals(
picking, price_unit, product_uom_qty, product_uom
)
bom = (
self.env["mrp.bom"]
.sudo()
._bom_find(
self.product_id, company_id=self.company_id.id, bom_type="distribution"
)[self.product_id]
)
if bom:
res["distribution_bom_id"] = bom.id
return res
def _get_po_line_moves(self):
res = super()._get_po_line_moves()
bom = (
self.env["mrp.bom"]
.sudo()
._bom_find(
self.product_id, company_id=self.company_id.id, bom_type="distribution"
)[self.product_id]
)
res |= self.move_ids.filtered(
lambda m: m.product_id in bom.bom_line_ids.product_id
)
return res

View File

@@ -0,0 +1,50 @@
# Copyright 2024 Tecnativa - Carlos Roca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import _, fields, models
class StockMove(models.Model):
_inherit = "stock.move"
distribution_bom_id = fields.Many2one("mrp.bom")
def action_open_distribution_wizard(self):
return {
"name": _("Distribution for %s") % self.product_id.display_name,
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "stock.move.distribution.wiz",
"target": "new",
"context": {"active_model": "stock.move", "active_id": self.id},
}
def _action_done(self, cancel_backorder=False):
distribution_moves = self.filtered(lambda m: m.distribution_bom_id)
new_moves = self.env["stock.move"]
for move in distribution_moves:
cancel_move = False
for sml in move.move_line_ids.filtered(
lambda ml, move=move: ml.product_id != move.product_id
):
# Create new moves with the corresponding product and the linked sml
new_moves += self.env["stock.move"].create(
{
"picking_id": sml.picking_id.id,
"product_id": sml.product_id.id,
"name": sml.product_id.display_name,
"purchase_line_id": move.purchase_line_id.id,
"product_uom": sml.product_uom_id.id,
"state": "assigned",
"location_id": sml.location_id.id,
"location_dest_id": sml.location_dest_id.id,
"price_unit": move.price_unit,
"move_line_ids": [(4, sml.id)],
}
)
cancel_move = True
if cancel_move:
move.state = "cancel"
return super(StockMove, self + new_moves)._action_done(
cancel_backorder=cancel_backorder
)

View File

@@ -0,0 +1,9 @@
To use this module, we will need to configure n different distribution-type Bills of
Materials (BoM) for n products. To do this, we will follow these steps:
#. Go to Manufacturing > Products > Bills of Materials
#. Click on Create
#. Select the product to be distributed in the receptions
#. Select the BoM type "Distribution"
#. In the components, add the products that can be filled in the reception (it is not
necessary to mark the quantity as it will default to 0)

View File

@@ -0,0 +1,4 @@
* `Tecnativa <https://www.tecnativa.com>`_:
* Pedro M. Baeza
* Carlos Roca

View File

@@ -0,0 +1,2 @@
This module allows you to buy a product that will be divided into others without
knowing the exact quantity of the others. That quantity will be filled in the picking.

View File

@@ -0,0 +1,12 @@
This module aims to address the need to receive a generic product, but until the
moment of reception, we do not know the quantity that we might receive of its
specific products.
Using kits was not suitable for us, because to account for a unit of the kit product,
the quantity specified in the BoM must be received. Therefore, we opted to define a
new type of BoM called distribution.
In this way, upon receiving a unit of any product added to the BoM, it will be
accounted for as a unit of the generic product and will be reflected in the svls as
separate products, but they will be accounted for in the purchase line as part of the
product.

View File

@@ -0,0 +1,5 @@
#. The current module is not designed to handle multi-step receipts. It operates on a
single-step process, making it unsuitable for more complex inventory management
scenarios.
#. The current module is not designed to handle multiple lots for a product.
#. The current module is not designed to handle multiple packages for a product.

View File

@@ -0,0 +1,10 @@
To see the module's functionality:
1. Create a new purchase order
2. Add the product for which the BoM has been created
3. Confirm the order
4. Go to the created delivery order
5. You will see a new button in the move that contains the product, click on it
6. A wizard will open to define the quantity of each product to distribute
7. By clicking on Distribute, the move lines will be added with the products from the
BoM

View File

@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
purchase_mrp_distribution.access_stock_move_distribution_wiz,access_stock_move_distribution_wiz,purchase_mrp_distribution.model_stock_move_distribution_wiz,stock.group_stock_user,1,1,1,1
purchase_mrp_distribution.access_stock_move_distribution_wiz_line,access_stock_move_distribution_wiz_line,purchase_mrp_distribution.model_stock_move_distribution_wiz_line,stock.group_stock_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 purchase_mrp_distribution.access_stock_move_distribution_wiz access_stock_move_distribution_wiz purchase_mrp_distribution.model_stock_move_distribution_wiz stock.group_stock_user 1 1 1 1
3 purchase_mrp_distribution.access_stock_move_distribution_wiz_line access_stock_move_distribution_wiz_line purchase_mrp_distribution.model_stock_move_distribution_wiz_line stock.group_stock_user 1 1 1 1

View File

@@ -0,0 +1,482 @@
<!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>Purchase MRP Distribution</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="purchase-mrp-distribution">
<h1 class="title">Purchase MRP Distribution</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:51d9b4cab80068fcea738841c68a570388273d7cde664d9603cad40b83184c13
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<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/manufacture/tree/15.0/purchase_mrp_distribution"><img alt="OCA/manufacture" src="https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/manufacture-15-0/manufacture-15-0-purchase_mrp_distribution"><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/manufacture&amp;target_branch=15.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 buy a product that will be divided into others without
knowing the exact quantity of the others. That quantity will be filled in the picking.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-3">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#changelog" id="toc-entry-4">Changelog</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-9">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>To use this module, we will need to configure n different distribution-type Bills of
Materials (BoM) for n products. To do this, we will follow these steps:</p>
<ol class="arabic simple">
<li>Go to Manufacturing &gt; Products &gt; Bills of Materials</li>
<li>Click on Create</li>
<li>Select the product to be distributed in the receptions</li>
<li>Select the BoM type “Distribution”</li>
<li>In the components, add the products that can be filled in the reception (it is not
necessary to mark the quantity as it will default to 0)</li>
</ol>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>To see the modules functionality:</p>
<ol class="arabic simple">
<li>Create a new purchase order</li>
<li>Add the product for which the BoM has been created</li>
<li>Confirm the order</li>
<li>Go to the created delivery order</li>
<li>You will see a new button in the move that contains the product, click on it</li>
<li>A wizard will open to define the quantity of each product to distribute</li>
<li>By clicking on Distribute, the move lines will be added with the products from the
BoM</li>
</ol>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h1>
<ol class="arabic simple">
<li>The current module is not designed to handle multi-step receipts. It operates on a
single-step process, making it unsuitable for more complex inventory management
scenarios.</li>
<li>The current module is not designed to handle multiple lots for a product.</li>
<li>The current module is not designed to handle multiple packages for a product.</li>
</ol>
</div>
<div class="section" id="changelog">
<h1><a class="toc-backref" href="#toc-entry-4">Changelog</a></h1>
<p>This module aims to address the need to receive a generic product, but until the
moment of reception, we do not know the quantity that we might receive of its
specific products.</p>
<p>Using kits was not suitable for us, because to account for a unit of the kit product,
the quantity specified in the BoM must be received. Therefore, we opted to define a
new type of BoM called distribution.</p>
<p>In this way, upon receiving a unit of any product added to the BoM, it will be
accounted for as a unit of the generic product and will be reflected in the svls as
separate products, but they will be accounted for in the purchase line as part of the
product.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/manufacture/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/manufacture/issues/new?body=module:%20purchase_mrp_distribution%0Aversion:%2015.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-6">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-7">Authors</a></h2>
<ul class="simple">
<li>Tecnaiva</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
<li>Carlos Roca</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-9">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/manufacture/tree/15.0/purchase_mrp_distribution">OCA/manufacture</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_purchase_mrp_distribution

View File

@@ -0,0 +1,105 @@
# Copyright 2024 Tecnativa - Carlos Roca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import Form, TransactionCase
class TestPurchaseMrpDistribution(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.category = cls.env["product.category"].create(
{
"name": "AVCO",
"property_cost_method": "average",
}
)
cls.product = cls.env["product.template"].create(
{
"name": "General product",
"categ_id": cls.category.id,
}
)
cls.subproduct_1 = cls.env["product.template"].create(
{
"name": "Product 1",
"categ_id": cls.category.id,
}
)
cls.subproduct_2 = cls.env["product.template"].create(
{
"name": "Product 2",
"categ_id": cls.category.id,
}
)
cls.bom = cls.env["mrp.bom"].create(
{
"product_tmpl_id": cls.product.id,
"type": "distribution",
"bom_line_ids": [
(
0,
0,
{
"product_id": cls.subproduct_1.product_variant_id.id,
},
),
(
0,
0,
{
"product_id": cls.subproduct_2.product_variant_id.id,
},
),
],
}
)
cls.partner = cls.env["res.partner"].create(
{
"name": "Partner",
}
)
def _create_po_picking(self):
purchase_form = Form(self.env["purchase.order"])
purchase_form.partner_id = self.partner
with purchase_form.order_line.new() as line_form:
line_form.product_id = self.product.product_variant_id
line_form.product_qty = 6
line_form.price_unit = 2
purchase = purchase_form.save()
purchase.button_confirm()
return purchase, purchase.picking_ids
def test_distribute_process(self):
purchase, picking = self._create_po_picking()
wiz_action = picking.move_lines.action_open_distribution_wizard()
wiz = (
self.env["stock.move.distribution.wiz"]
.with_context(**wiz_action["context"])
.create({})
)
self.assertIn(self.subproduct_1.product_variant_id, wiz.line_ids.product_id)
self.assertIn(self.subproduct_2.product_variant_id, wiz.line_ids.product_id)
wiz.line_ids.quantity = 3
wiz.button_distribute_qty()
self.assertEqual(len(picking.move_lines), 1)
self.assertEqual(len(picking.move_lines.move_line_ids), 2)
for sml in picking.move_lines.move_line_ids:
self.assertEqual(sml.qty_done, 3)
original_move = picking.move_lines
picking.button_validate()
self.assertEqual(len(picking.move_lines), 3)
self.assertEqual(original_move.state, "cancel")
self.assertIn(
self.subproduct_1.product_variant_id, picking.move_lines.product_id
)
self.assertIn(
self.subproduct_2.product_variant_id, picking.move_lines.product_id
)
self.assertEqual(purchase.order_line.qty_received, 6)
svl_action = picking.action_view_stock_valuation_layers()
svls = self.env["stock.valuation.layer"].search(svl_action["domain"])
for svl in svls:
self.assertEqual(svl.quantity, 3)
self.assertEqual(svl.value, 6)

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="purchase_order_form" model="ir.ui.view">
<field name="model">mrp.bom</field>
<field name="inherit_id" ref="mrp.mrp_bom_form_view" />
<field name="arch" type="xml">
<xpath expr="//field[@name='type']/../p" position="after">
<p
colspan="2"
class="oe_grey oe_edit_only"
attrs="{'invisible': [('type','!=','distribution')]}"
>
A BoM of type distribution is used to select the quantities of components.
<ul>
<li>
At a Stock Transfer.
</li>
</ul>
</p>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_picking_form" model="ir.ui.view">
<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']/tree/field[@name='quantity_done']"
position="after"
>
<field name="distribution_bom_id" invisible="1" />
<button
name="action_open_distribution_wizard"
type="object"
icon="fa-sitemap"
attrs="{'invisible': ['|', ('distribution_bom_id', '=', False), ('state', 'in', ['done', 'cancel'])]}"
/>
</xpath>
</field>
</record>
</odoo>

View File

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

View File

@@ -0,0 +1,98 @@
# Copyright 2024 Tecnativa - Carlos Roca
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import api, fields, models
class StockMoveDistributionWiz(models.TransientModel):
_name = "stock.move.distribution.wiz"
_description = "Wizard to distribute product qty to diferent products"
@api.model
def default_get(self, fields):
ctx = self.env.context.copy()
res = super().default_get(fields)
if ctx.get("active_id") and ctx.get("active_model") == "stock.move":
move = self.env["stock.move"].browse(ctx["active_id"])
lines = []
for bom_line in move.distribution_bom_id.bom_line_ids:
if move_lines := move.move_line_ids.filtered(
lambda ml, bom_line=bom_line: ml.product_id == bom_line.product_id
):
for sml in move_lines:
lines.append(
(
0,
0,
{
"product_id": bom_line.product_id.id,
"quantity": sml.qty_done,
"uom_id": bom_line.product_uom_id.id,
"lot_id": sml.lot_id.id,
"package_id": sml.result_package_id.id,
"company_id": sml.company_id.id,
},
)
)
else:
lines.append(
(
0,
0,
{
"product_id": bom_line.product_id.id,
"quantity": 0,
"uom_id": bom_line.product_uom_id.id,
"company_id": move.company_id.id,
},
)
)
res.update(
{
"move_id": move.id,
"line_ids": lines,
}
)
return res
move_id = fields.Many2one("stock.move")
line_ids = fields.One2many("stock.move.distribution.wiz.line", "wizard_id")
demand_quantity = fields.Float(related="move_id.product_uom_qty")
move_uom_id = fields.Many2one(related="move_id.product_uom")
def button_distribute_qty(self):
self.ensure_one()
# Clean actual move lines
self.move_id.move_line_ids.sudo().unlink()
for line in self.line_ids:
# Create new move_lines
if line.quantity:
self.env["stock.move.line"].create(
{
"move_id": self.move_id.id,
"product_id": line.product_id.id,
"qty_done": line.quantity,
"product_uom_id": line.uom_id.id,
"location_id": self.move_id.location_id.id,
"location_dest_id": self.move_id.location_dest_id.id,
"picking_id": self.move_id.picking_id.id,
"company_id": self.move_id.company_id.id,
"lot_id": line.lot_id.id,
"result_package_id": line.package_id.id,
}
)
if self.move_id.move_line_ids:
self.move_id.state = "assigned"
class StockMoveDistributionWizLine(models.TransientModel):
_name = "stock.move.distribution.wiz.line"
_description = "Lines of wizard to distribute product qty to diferent products"
wizard_id = fields.Many2one("stock.move.distribution.wiz")
product_id = fields.Many2one("product.product")
quantity = fields.Float(digits="Product Unit of Measure")
uom_id = fields.Many2one("uom.uom")
lot_id = fields.Many2one("stock.production.lot")
package_id = fields.Many2one("stock.production.lot")
company_id = fields.Many2one("res.company")

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="stock_move_distribution_wiz_form" model="ir.ui.view">
<field name="name">Stock Move Distribution Wiz Form</field>
<field name="model">stock.move.distribution.wiz</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="move_id" invisible="1" />
<label for="demand_quantity" />
<div>
<field name="demand_quantity" />
<field name="move_uom_id" groups="uom.group_uom" />
</div>
</group>
<group>
<field name="line_ids" nolabel="1">
<tree editable="bottom" create="0" delete="0">
<field name="company_id" invisible="1" />
<field name="product_id" readonly="1" force_save="1" />
<field
name="lot_id"
groups="stock.group_production_lot"
domain="[('product_id', '=', product_id), ('company_id', '=', company_id)]"
context="{
'default_company_id': company_id,
'default_product_id': product_id,
}"
/>
<field
name="package_id"
groups="stock.group_tracking_lot"
/>
<field name="quantity" />
<field name="uom_id" groups="uom.group_uom" />
</tree>
</field>
</group>
</sheet>
<footer>
<button
name="button_distribute_qty"
string="Distribute"
type="object"
class="oe_highlight"
/>
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
../../../../purchase_mrp_distribution

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)