Merge PR #1706 into 13.0

Signed-off-by LoisRForgeFlow
This commit is contained in:
OCA-git-bot
2023-05-18 14:25:42 +00:00
13 changed files with 253 additions and 0 deletions

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,18 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Stock Picking Origin Destination Link",
"summary": """
This addon link the pickings with their respective Origin and Destination Pickings.
""",
"version": "13.0.1.0.0",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/stock-logistics-warehouse",
"category": "Warehouse Management",
"license": "AGPL-3",
"depends": ["stock"],
"data": ["views/stock_picking_views.xml"],
"installable": True,
"pre_init_hook": "pre_init_hook",
"post_init_hook": "post_init_hook",
}

View File

@@ -0,0 +1,41 @@
# Copyright 2023 ForgeFlow, S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import SUPERUSER_ID, api
from odoo.tools import sql
_logger = logging.getLogger(__name__)
def pre_init_hook(cr):
_logger.info(
"Create temporary table to avoid the automatic launch of the compute method"
)
if not sql.table_exists(cr, "stock_picking_orig_dest_rel"):
cr.execute("CREATE TABLE stock_picking_orig_dest_rel (temp INTEGER)")
def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Dropping temporary table")
cr.execute("DROP TABLE stock_picking_orig_dest_rel")
_logger.info("Creating new table via ORM")
StockPicking = env["stock.picking"]
StockPicking._fields["orig_picking_ids"].update_db(StockPicking, False)
StockPicking._fields["dest_picking_ids"].update_db(StockPicking, False)
_logger.info("Filling Origin and Destination Picking relation table")
query = """
WITH query AS (
SELECT spo.id AS orig_picking_id, spd.id AS dest_picking_id
FROM stock_move_move_rel smml
JOIN stock_move smo ON smo.id = smml.move_orig_id
JOIN stock_move smd ON smd.id = smml.move_dest_id
JOIN stock_picking spo ON smo.picking_id = spo.id
JOIN stock_picking spd ON smd.picking_id = spd.id
GROUP BY spo.id, spd.id
)
INSERT INTO stock_picking_orig_dest_rel (orig_picking_id, dest_picking_id)
SELECT * FROM query;
"""
cr.execute(query)

View File

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

View File

@@ -0,0 +1,51 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
class StockPicking(models.Model):
_inherit = "stock.picking"
orig_picking_ids = fields.Many2many(
comodel_name="stock.picking",
relation="stock_picking_orig_dest_rel",
column1="dest_picking_id",
column2="orig_picking_id",
string="Origin Transfer/s",
compute="_compute_origin_dest_picking",
store=True,
readonly=True,
)
dest_picking_ids = fields.Many2many(
comodel_name="stock.picking",
relation="stock_picking_orig_dest_rel",
column1="orig_picking_id",
column2="dest_picking_id",
string="Destination Transfer/s",
compute="_compute_origin_dest_picking",
store=True,
readonly=True,
)
def _get_orig_picking_ids(self):
"""
Returns the Origin Pickings from a single picking. Done in method to be
inherited in other modules, if needed.
"""
self.ensure_one()
return self.mapped("move_lines.move_orig_ids.picking_id")
def _get_dest_picking_ids(self):
"""
Returns the Destination Pickings from a single picking. Done in method to be
inherited in other modules, if needed.
"""
self.ensure_one()
return self.mapped("move_lines.move_dest_ids.picking_id")
@api.depends("move_lines.move_orig_ids", "move_lines.move_dest_ids")
def _compute_origin_dest_picking(self):
for picking in self:
picking.orig_picking_ids = picking._get_orig_picking_ids()
picking.dest_picking_ids = picking._get_dest_picking_ids()

View File

@@ -0,0 +1,2 @@
* `ForgeFlow <https://www.forgeflow.com>`
* Guillem Casassas <guillem.casassas@forgeflow.com>

View File

@@ -0,0 +1,5 @@
This module adds the link between the origin and the destination pickings through a technical field. It can latter be added in the views to show it to the user.
For each picking in the system, it will link it to their respective Origin and Destination pickings.
It also adds the possibility to view the Origin or Destination of a certain transfer in the list view by adding two additional columns which are hidden by default. Also, you can filter and group by the transfers.

View File

@@ -0,0 +1 @@
* This module is very similar to *stock_picking_show_linked* in terms of funcionalities being added. In future versions, we should consider merging the two modules into a single one.

View File

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

View File

@@ -0,0 +1,87 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import SavepointCase
class TestPickingOrigDestLink(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
# Models
cls.product_model = cls.env["product.product"]
cls.picking_model = cls.env["stock.picking"]
cls.partner_model = cls.env["res.partner"]
cls.move_model = cls.env["stock.move"]
# Created records
cls.product = cls.product_model.create({"name": "Test Product"})
cls.partner = cls.partner_model.create({"name": "Test Partner"})
# Data records
cls.pick_type_in = cls.env.ref("stock.picking_type_in")
cls.pick_type_out = cls.env.ref("stock.picking_type_out")
cls.stock_location = cls.env.ref("stock.stock_location_stock")
cls.customers_location = cls.env.ref("stock.stock_location_customers")
cls.suppliers_location = cls.env.ref("stock.stock_location_suppliers")
@classmethod
def _create_in_picking(cls):
picking = cls.picking_model.create(
{
"partner_id": cls.partner.id,
"picking_type_id": cls.pick_type_in.id,
"location_id": cls.suppliers_location.id,
"location_dest_id": cls.stock_location.id,
}
)
move_vals = {
"picking_id": picking.id,
"product_id": cls.product.id,
"location_dest_id": cls.stock_location.id,
"location_id": cls.suppliers_location.id,
"name": cls.product.name,
"product_uom_qty": 1,
"product_uom": cls.product.uom_id.id,
}
cls.move_model.create(move_vals)
return picking
@classmethod
def _create_out_picking(cls):
picking = cls.picking_model.create(
{
"partner_id": cls.partner.id,
"picking_type_id": cls.pick_type_out.id,
"location_id": cls.stock_location.id,
"location_dest_id": cls.customers_location.id,
}
)
move_vals = {
"picking_id": picking.id,
"product_id": cls.product.id,
"location_id": cls.stock_location.id,
"location_dest_id": cls.customers_location.id,
"name": cls.product.name,
"product_uom_qty": 1,
"product_uom": cls.product.uom_id.id,
}
cls.move_model.create(move_vals)
return picking
@classmethod
def _link_moves_from_pickings(cls, in_picking, out_picking):
in_move_ids = in_picking.move_lines
out_move_ids = out_picking.move_lines
return in_move_ids.write({"move_dest_ids": out_move_ids})
def test_01_in_out_pickings(self):
# create in and out picking and links their moves
in_pick = self._create_in_picking()
out_pick = self._create_out_picking()
result = self._link_moves_from_pickings(in_pick, out_pick)
self.assertTrue(result)
# check that pickings have also been linked
self.assertEqual(in_pick.dest_picking_ids, out_pick)
self.assertEqual(out_pick.orig_picking_ids, in_pick)

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="view_stock_picking_tree" model="ir.ui.view">
<field name="name">stock.picking.tree - stock_picking_orig_dest_link</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.vpicktree" />
<field name="arch" type="xml">
<field name="activity_exception_decoration" position="after">
<field
name="orig_picking_ids"
widget="many2many_tags"
optional="hide"
/>
<field
name="dest_picking_ids"
widget="many2many_tags"
optional="hide"
/>
</field>
</field>
</record>
<record id="view_picking_internal_search" model="ir.ui.view">
<field
name="name"
>stock.picking.search - stock_picking_orig_dest_link</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_internal_search" />
<field name="arch" type="xml">
<field name="picking_type_id" position="after">
<field name="orig_picking_ids" />
<field name="dest_picking_ids" />
</field>
</field>
</record>
</data>
</odoo>