Merge PR #2115 into 16.0

Signed-off-by rousseldenis
This commit is contained in:
OCA-git-bot
2024-07-29 06:56:34 +00:00
9 changed files with 117 additions and 102 deletions

View File

@@ -62,8 +62,8 @@ If you want to transfer a full quant:
- Select the quantities which you want move to another location - Select the quantities which you want move to another location
If you go to the Inventory Dashboard you can see the button "Move from If you go to the Inventory Dashboard you can see the button "Move from
location" in each of the picking types (only applicable to internal location" in each of the picking types (only applicable to internal and
transfers). Press it and you will be directed to the wizard. outgoing transfers). Press it and you will be directed to the wizard.
|image1| |image1|
@@ -143,6 +143,8 @@ Contributors
- Aung Ko Ko Lin - Aung Ko Ko Lin
- Laurent Mignon <laurent.mignon@acsone.eu>
Maintainers Maintainers
----------- -----------

View File

@@ -13,3 +13,4 @@
- Abraham Anes \<<abraham@studio73.es>\> - Abraham Anes \<<abraham@studio73.es>\>
- Quartile \<<https://www.quartile.co>\> - Quartile \<<https://www.quartile.co>\>
- Aung Ko Ko Lin - Aung Ko Ko Lin
- Laurent Mignon \<<laurent.mignon@acsone.eu>\>

View File

@@ -1,43 +1,37 @@
- A new menu item Operations \> Move from location... opens a wizard - A new menu item Operations \> Move from location... opens a wizard where 2 locations
where 2 locations can be specified. can be specified.
- Select origin and destination locations and press "IMMEDIATE TRANSFER" - Select origin and destination locations and press "IMMEDIATE TRANSFER" or "PLANNED
or "PLANNED TRANSFER" TRANSFER"
- Press ADD ALL button to add all products available - Press ADD ALL button to add all products available
- Those lines can be edited. Move quantity can't be more than a max - Those lines can be edited. Move quantity can't be more than a max available quantity
available quantity
- Move doesn't care about the reservations and will move stuff anyway - Move doesn't care about the reservations and will move stuff anyway
- If during your operation with the wizard the real quantity will change - If during your operation with the wizard the real quantity will change it will move
it will move only the available quantity at the button press only the available quantity at the button press
- Products will be moved and a form view of picking that did that will - Products will be moved and a form view of picking that did that will show up
show up - If "PLANNED TRANSFER" is used - the picking won't be validated automatically
- If "PLANNED TRANSFER" is used - the picking won't be validated
automatically
If you want to transfer a full quant: If you want to transfer a full quant:
- Go to Inventory \> Products \> Products and click "On hand" smart - Go to Inventory \> Products \> Products and click "On hand" smart button or Inventory
button or Inventory \> Reporting \> Inventory, the quants view will be \> Reporting \> Inventory, the quants view will be opened.
opened.
- Select the quantities which you want move to another location - Select the quantities which you want move to another location
If you go to the Inventory Dashboard you can see the button "Move from If you go to the Inventory Dashboard you can see the button "Move from location" in each
location" in each of the picking types (only applicable to internal of the picking types (only applicable to internal and outgoing transfers). Press it and
transfers). Press it and you will be directed to the wizard. you will be directed to the wizard.
![](https://user-images.githubusercontent.com/147538094/281480833-208ea309-0bad-43e7-bd6f-8384520afe00.png) ![](https://user-images.githubusercontent.com/147538094/281480833-208ea309-0bad-43e7-bd6f-8384520afe00.png)
To enable this option, check "Show Move On Hand Stock" in the Picking Type configuration. To enable this option, check "Show Move On Hand Stock" in the Picking Type
configuration.
![](https://user-images.githubusercontent.com/147538094/281479487-45fa4bde-36be-4ba1-8d54-8e707b89459e.png) ![](https://user-images.githubusercontent.com/147538094/281479487-45fa4bde-36be-4ba1-8d54-8e707b89459e.png)
If you want transfer everything from stock.location If you want transfer everything from stock.location
On a draft picking, add a button to fill with moves lines for all On a draft picking, add a button to fill with moves lines for all products in the source
products in the source destination. This allows to create a picking to destination. This allows to create a picking to move all the content of a location. The
move all the content of a location. The Origin Location must have stock. Origin Location must have stock. The Destination Location has to be a final location. If
The Destination Location has to be a final location. some quants are not available (i.e. reserved) the picking will be in partially available
If some quants are not available state and reserved moves won't be listed in the operations. Use barcode interface to
(i.e. reserved) the picking will be in partially available state and scan a location and create an empty picking. Then use the fill with stock button.
reserved moves won't be listed in the operations. Use barcode interface
to scan a location and create an empty picking. Then use the fill with
stock button.

View File

@@ -412,8 +412,8 @@ opened.</li>
<li>Select the quantities which you want move to another location</li> <li>Select the quantities which you want move to another location</li>
</ul> </ul>
<p>If you go to the Inventory Dashboard you can see the button “Move from <p>If you go to the Inventory Dashboard you can see the button “Move from
location” in each of the picking types (only applicable to internal location” in each of the picking types (only applicable to internal and
transfers). Press it and you will be directed to the wizard.</p> outgoing transfers). Press it and you will be directed to the wizard.</p>
<p><img alt="image1" src="https://user-images.githubusercontent.com/147538094/281480833-208ea309-0bad-43e7-bd6f-8384520afe00.png" /></p> <p><img alt="image1" src="https://user-images.githubusercontent.com/147538094/281480833-208ea309-0bad-43e7-bd6f-8384520afe00.png" /></p>
<p>To enable this option, check “Show Move On Hand Stock” in the Picking <p>To enable this option, check “Show Move On Hand Stock” in the Picking
Type configuration.</p> Type configuration.</p>
@@ -483,6 +483,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
<li>Aung Ko Ko Lin</li> <li>Aung Ko Ko Lin</li>
</ul> </ul>
</li> </li>
<li>Laurent Mignon &lt;<a class="reference external" href="mailto:laurent.mignon&#64;acsone.eu">laurent.mignon&#64;acsone.eu</a>&gt;</li>
</ul> </ul>
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">

View File

@@ -92,46 +92,49 @@ class TestsCommon(common.TransactionCase):
) )
cls.package = cls.env["stock.quant.package"].create({}) cls.package = cls.env["stock.quant.package"].create({})
cls.package1 = cls.env["stock.quant.package"].create({}) cls.package1 = cls.env["stock.quant.package"].create({})
cls.package2 = cls.env["stock.quant.package"].create({}) cls.package2 = cls.env["stock.quant.package"].create({})
def setup_product_amounts(self): @classmethod
self.set_product_amount(self.product_no_lots, self.internal_loc_1, 123) def setup_product_amounts(cls):
self.set_product_amount( cls.set_product_amount(cls.product_no_lots, cls.internal_loc_1, 123)
self.product_lots, self.internal_loc_1, 1.0, lot_id=self.lot1 cls.set_product_amount(
cls.product_lots, cls.internal_loc_1, 1.0, lot_id=cls.lot1
) )
self.set_product_amount( cls.set_product_amount(
self.product_lots, self.internal_loc_1, 1.0, lot_id=self.lot2 cls.product_lots, cls.internal_loc_1, 1.0, lot_id=cls.lot2
) )
self.set_product_amount( cls.set_product_amount(
self.product_lots, self.internal_loc_1, 1.0, lot_id=self.lot3 cls.product_lots, cls.internal_loc_1, 1.0, lot_id=cls.lot3
) )
self.set_product_amount( cls.set_product_amount(
self.product_package, cls.product_package,
self.internal_loc_1, cls.internal_loc_1,
1.0, 1.0,
lot_id=self.lot4, lot_id=cls.lot4,
package_id=self.package, package_id=cls.package,
) )
self.set_product_amount( cls.set_product_amount(
self.product_package, cls.product_package,
self.internal_loc_1, cls.internal_loc_1,
1.0, 1.0,
lot_id=self.lot4, lot_id=cls.lot4,
package_id=self.package1, package_id=cls.package1,
) )
self.set_product_amount( cls.set_product_amount(
self.product_package, cls.product_package,
self.internal_loc_1, cls.internal_loc_1,
1.0, 1.0,
lot_id=self.lot5, lot_id=cls.lot5,
package_id=self.package2, package_id=cls.package2,
owner_id=self.partner, owner_id=cls.partner,
) )
@classmethod
def set_product_amount( def set_product_amount(
self, product, location, amount, lot_id=None, package_id=None, owner_id=None cls, product, location, amount, lot_id=None, package_id=None, owner_id=None
): ):
self.env["stock.quant"]._update_available_quantity( cls.env["stock.quant"]._update_available_quantity(
product, product,
location, location,
amount, amount,

View File

@@ -8,9 +8,10 @@ from .test_common import TestsCommon
class TestMoveLocation(TestsCommon): class TestMoveLocation(TestsCommon):
def setUp(self): @classmethod
super().setUp() def setUpClass(cls):
self.setup_product_amounts() super().setUpClass()
cls.setup_product_amounts()
def test_move_location_wizard(self): def test_move_location_wizard(self):
"""Test a simple move.""" """Test a simple move."""

View File

@@ -8,7 +8,7 @@
<field name="show_operations" position="after"> <field name="show_operations" position="after">
<field <field
name="show_move_onhand" name="show_move_onhand"
attrs='{"invisible": [("code", "not in", ["internal"])]}' attrs='{"invisible": [("code", "not in", ["internal", "outgoing"])]}'
/> />
</field> </field>
</field> </field>

View File

@@ -71,7 +71,7 @@ class StockMoveLocationWizard(models.TransientModel):
for rec in self: for rec in self:
picking_type = self.env["stock.picking.type"] picking_type = self.env["stock.picking.type"]
base_domain = [ base_domain = [
("code", "=", "internal"), ("code", "in", ("internal", "outgoing")),
("warehouse_id.company_id", "=", company_id), ("warehouse_id.company_id", "=", company_id),
] ]
if rec.origin_location_id: if rec.origin_location_id:
@@ -303,25 +303,32 @@ class StockMoveLocationWizard(models.TransientModel):
) )
return action return action
def _get_quants_domain(self):
return [("location_id", "=", self.origin_location_id.id)]
def _get_group_quants(self): def _get_group_quants(self):
location_id = self.origin_location_id domain = self._get_quants_domain()
# Using sql as search_group doesn't support aggregation functions result = self.env["stock.quant"].read_group(
# leading to overhead in queries to DB domain=domain,
query = """ fields=[
SELECT product_id, lot_id, package_id, owner_id, SUM(quantity) AS quantity, "product_id",
SUM(reserved_quantity) AS reserved_quantity "lot_id",
FROM stock_quant "package_id",
WHERE location_id = %s "owner_id",
GROUP BY product_id, lot_id, package_id, owner_id "quantity:sum",
""" "reserved_quantity:sum",
self.env.cr.execute(query, (location_id.id,)) ],
return self.env.cr.dictfetchall() groupby=["product_id", "lot_id", "package_id", "owner_id"],
orderby="id",
lazy=False,
)
return result
def _get_stock_move_location_lines_values(self): def _get_stock_move_location_lines_values(self):
product_obj = self.env["product.product"] product_obj = self.env["product.product"]
product_data = [] product_data = []
for group in self._get_group_quants(): for group in self._get_group_quants():
product = product_obj.browse(group.get("product_id")).exists() product = product_obj.browse(group["product_id"][0]).exists()
# Apply the putaway strategy # Apply the putaway strategy
location_dest_id = ( location_dest_id = (
self.apply_putaway_strategy self.apply_putaway_strategy
@@ -337,24 +344,20 @@ class StockMoveLocationWizard(models.TransientModel):
"origin_location_id": self.origin_location_id.id, "origin_location_id": self.origin_location_id.id,
"destination_location_id": location_dest_id, "destination_location_id": location_dest_id,
# cursor returns None instead of False # cursor returns None instead of False
"lot_id": group.get("lot_id") or False, "lot_id": group["lot_id"][0] if group.get("lot_id") else False,
"package_id": group.get("package_id") or False, "package_id": group["package_id"][0]
"owner_id": group.get("owner_id") or False, if group.get("package_id")
else False,
"owner_id": group["owner_id"][0]
if group.get("owner_id")
else False,
"product_uom_id": product.uom_id.id, "product_uom_id": product.uom_id.id,
"custom": False, "custom": False,
} }
) )
return product_data return product_data
@api.onchange("origin_location_id") def _reset_stock_move_location_lines(self):
def onchange_origin_location(self):
# Get origin_location_disable context key to prevent load all origin
# location products when user opens the wizard from stock quants to
# move it to other location.
if (
not self.env.context.get("origin_location_disable")
and self.origin_location_id
):
lines = [] lines = []
line_model = self.env["wiz.stock.move.location.line"] line_model = self.env["wiz.stock.move.location.line"]
for line_val in self._get_stock_move_location_lines_values(): for line_val in self._get_stock_move_location_lines_values():
@@ -368,6 +371,17 @@ class StockMoveLocationWizard(models.TransientModel):
{"stock_move_location_line_ids": [(6, 0, [line.id for line in lines])]} {"stock_move_location_line_ids": [(6, 0, [line.id for line in lines])]}
) )
@api.onchange("origin_location_id")
def onchange_origin_location(self):
# Get origin_location_disable context key to prevent load all origin
# location products when user opens the wizard from stock quants to
# move it to other location.
if (
not self.env.context.get("origin_location_disable")
and self.origin_location_id
):
self._reset_stock_move_location_lines()
def clear_lines(self): def clear_lines(self):
self._clear_lines() self._clear_lines()
return {"type": "ir.action.do_nothing"} return {"type": "ir.action.do_nothing"}

View File

@@ -10,18 +10,15 @@
<form> <form>
<sheet> <sheet>
<div class="oe_button_box" name="button_box" /> <div class="oe_button_box" name="button_box" />
<div> <group name="options">
<label for="edit_locations">
Edit Locations
</label>
<field name="edit_locations" widget="boolean_toggle" /> <field name="edit_locations" widget="boolean_toggle" />
</div> <field
<div groups="stock.group_stock_multi_locations"> name="apply_putaway_strategy"
<label for="apply_putaway_strategy"> string="Apply putaway strategy for moving products"
Apply putaway strategy for moving products widget="boolean_toggle"
</label> groups="stock.group_stock_multi_locations"
<field name="apply_putaway_strategy" widget="boolean_toggle" /> />
</div> </group>
<group name="picking_type"> <group name="picking_type">
<field name="picking_type_id" /> <field name="picking_type_id" />
</group> </group>
@@ -37,6 +34,8 @@
attrs="{'readonly': [('destination_location_disable', '=', True)]}" attrs="{'readonly': [('destination_location_disable', '=', True)]}"
/> />
</group> </group>
<group name="filters">
</group>
<group name="lines"> <group name="lines">
<field <field
name="stock_move_location_line_ids" name="stock_move_location_line_ids"