mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[16.0][ADD] stock_available_immediately_exclude_location
This commit is contained in:
8
stock_available_immediately_exclude_location/README.rst
Normal file
8
stock_available_immediately_exclude_location/README.rst
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
==================================================
|
||||||
|
Exclude locations from immediately usable quantity
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
|
!! changes will be overwritten. !!
|
||||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
3
stock_available_immediately_exclude_location/__init__.py
Normal file
3
stock_available_immediately_exclude_location/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from . import models
|
||||||
14
stock_available_immediately_exclude_location/__manifest__.py
Normal file
14
stock_available_immediately_exclude_location/__manifest__.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Copyright 2023 ACSONE SA/NV
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Exclude locations from immediately usable quantity",
|
||||||
|
"version": "16.0.1.0.0",
|
||||||
|
"website": "https://github.com/OCA/stock-logistics-availability",
|
||||||
|
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
|
||||||
|
"license": "AGPL-3",
|
||||||
|
"depends": ["stock_available_immediately"],
|
||||||
|
"data": ["views/stock_location.xml"],
|
||||||
|
"category": "Hidden",
|
||||||
|
"installable": True,
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * stock_available_immediately_exclude_location
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2023-01-18 14:11+0000\n"
|
||||||
|
"PO-Revision-Date: 2023-01-18 14:11+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: stock_available_immediately_exclude_location
|
||||||
|
#: model:ir.model.fields,field_description:stock_available_immediately_exclude_location.field_stock_location__exclude_from_immediately_usable_qty
|
||||||
|
msgid "Exclude from immediately usable quantity"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: stock_available_immediately_exclude_location
|
||||||
|
#: model_terms:ir.ui.view,arch_db:stock_available_immediately_exclude_location.stock_location_search_view
|
||||||
|
msgid "Excluded from immediately usable quantities"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: stock_available_immediately_exclude_location
|
||||||
|
#: model:ir.model,name:stock_available_immediately_exclude_location.model_stock_location
|
||||||
|
msgid "Inventory Locations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: stock_available_immediately_exclude_location
|
||||||
|
#: model:ir.model,name:stock_available_immediately_exclude_location.model_product_product
|
||||||
|
msgid "Product Variant"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: stock_available_immediately_exclude_location
|
||||||
|
#: model:ir.model.fields,help:stock_available_immediately_exclude_location.field_stock_location__exclude_from_immediately_usable_qty
|
||||||
|
msgid "This property is not inherited by children locations"
|
||||||
|
msgstr ""
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from . import product_product
|
||||||
|
from . import stock_location
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Copyright 2023 ACSONE SA/NV
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from odoo import models
|
||||||
|
from odoo.osv import expression
|
||||||
|
|
||||||
|
|
||||||
|
class ProductProduct(models.Model):
|
||||||
|
|
||||||
|
_inherit = "product.product"
|
||||||
|
|
||||||
|
def _compute_available_quantities_dict(self):
|
||||||
|
"""
|
||||||
|
change the way immediately_usable_qty is computed by deducing the quants
|
||||||
|
in excluded locations
|
||||||
|
"""
|
||||||
|
res, stock_dict = super()._compute_available_quantities_dict()
|
||||||
|
exclude_location_ids = (
|
||||||
|
self._get_locations_excluded_from_immediately_usable_qty().ids
|
||||||
|
)
|
||||||
|
|
||||||
|
if exclude_location_ids:
|
||||||
|
excluded_qty_dict = self.with_context(
|
||||||
|
location=exclude_location_ids, compute_child=False
|
||||||
|
)._compute_quantities_dict(
|
||||||
|
self._context.get("lot_id"),
|
||||||
|
self._context.get("owner_id"),
|
||||||
|
self._context.get("package_id"),
|
||||||
|
self._context.get("from_date"),
|
||||||
|
self._context.get("to_date"),
|
||||||
|
)
|
||||||
|
|
||||||
|
for product_id in res:
|
||||||
|
if exclude_location_ids:
|
||||||
|
res[product_id]["immediately_usable_qty"] -= excluded_qty_dict[
|
||||||
|
product_id
|
||||||
|
]["qty_available"]
|
||||||
|
return res, stock_dict
|
||||||
|
|
||||||
|
def _get_locations_excluded_from_immediately_usable_qty(self):
|
||||||
|
return self.env["stock.location"].search(
|
||||||
|
self._get_domain_location_excluded_from_immediately_usable_qty()
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_domain_location_excluded_from_immediately_usable_qty(self):
|
||||||
|
"""
|
||||||
|
Parses the context and returns a list of location_ids based on it that
|
||||||
|
should be excluded from the immediately_usable_qty
|
||||||
|
"""
|
||||||
|
quant_domain = self.env["product.product"]._get_domain_locations()[0]
|
||||||
|
# Adapt the domain on quants (which normally contains only company_id and
|
||||||
|
# location_id) for stock.location and add the criteria on
|
||||||
|
# exclude_from_immediately_usable_qty to it.
|
||||||
|
# Be sure to exclude potential fields that couldn't belong to stock.location
|
||||||
|
# and replace such term by something True domain compatible
|
||||||
|
location_domain = []
|
||||||
|
location_fields = self.env["stock.location"].fields_get()
|
||||||
|
for element in quant_domain:
|
||||||
|
if expression.is_leaf(element) and element[0] not in location_fields:
|
||||||
|
# exclude the element from domain and replace by something True
|
||||||
|
location_domain.append((1, "=", 1)) # True and domain compatible
|
||||||
|
elif expression.is_leaf(element):
|
||||||
|
location_domain.append(
|
||||||
|
(element[0].replace("location_id.", ""), element[1], element[2])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
location_domain.append(element)
|
||||||
|
return expression.AND(
|
||||||
|
[location_domain, [("exclude_from_immediately_usable_qty", "=", True)]]
|
||||||
|
)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Copyright 2023 ACSONE SA/NV
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class StockLocation(models.Model):
|
||||||
|
|
||||||
|
_inherit = "stock.location"
|
||||||
|
|
||||||
|
exclude_from_immediately_usable_qty = fields.Boolean(
|
||||||
|
"Exclude from immediately usable quantity",
|
||||||
|
default=False,
|
||||||
|
index=True,
|
||||||
|
help="This property is not inherited by children locations",
|
||||||
|
)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
* Author: Hughes Damry <hughes.damry@acsone.eu>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
This module adds a boolean to exclude the tagged stock locations
|
||||||
|
from the stock available immediately.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
@@ -0,0 +1 @@
|
|||||||
|
from . import test_stock_exclude_location
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Copyright 2023 ACSONE SA/NV
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestStockLogisticsWarehouse(TransactionCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls) -> None:
|
||||||
|
super().setUpClass()
|
||||||
|
cls.move_model = cls.env["stock.move"]
|
||||||
|
cls.uom_unit = cls.env.ref("uom.product_uom_unit")
|
||||||
|
cls.product = cls.env["product.product"].create(
|
||||||
|
{
|
||||||
|
"name": "Product Test",
|
||||||
|
"uom_id": cls.uom_unit.id,
|
||||||
|
"type": "product",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cls.supplier_location = cls.env.ref("stock.stock_location_suppliers")
|
||||||
|
cls.stock_location = cls.env.ref("stock.stock_location_stock")
|
||||||
|
cls.pack_location = cls.env.ref("stock.location_pack_zone")
|
||||||
|
(cls.stock_location | cls.pack_location).write({"active": True})
|
||||||
|
|
||||||
|
def test01(self):
|
||||||
|
location_ids = (self.stock_location | self.pack_location).ids
|
||||||
|
ctx_loc = {"location": location_ids}
|
||||||
|
move_stock = self.move_model.create(
|
||||||
|
{
|
||||||
|
"location_id": self.supplier_location.id,
|
||||||
|
"location_dest_id": self.stock_location.id,
|
||||||
|
"name": "MOVE STOCK ",
|
||||||
|
"product_id": self.product.id,
|
||||||
|
"product_uom": self.product.uom_id.id,
|
||||||
|
"product_uom_qty": 15,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
move_pack = self.move_model.create(
|
||||||
|
{
|
||||||
|
"location_id": self.supplier_location.id,
|
||||||
|
"location_dest_id": self.pack_location.id,
|
||||||
|
"name": "MOVE PACK ",
|
||||||
|
"product_id": self.product.id,
|
||||||
|
"product_uom": self.product.uom_id.id,
|
||||||
|
"product_uom_qty": 5,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(move_stock | move_pack)._action_confirm()
|
||||||
|
(move_stock | move_pack)._action_assign()
|
||||||
|
move_stock.move_line_ids.write({"qty_done": 7.0})
|
||||||
|
move_stock._action_done()
|
||||||
|
q = self.product.with_context(**ctx_loc).immediately_usable_qty
|
||||||
|
self.assertEqual(q, 7.0)
|
||||||
|
move_pack.move_line_ids.write({"qty_done": 4.0})
|
||||||
|
move_pack._action_done()
|
||||||
|
q = self.product.with_context(**ctx_loc).immediately_usable_qty
|
||||||
|
self.assertEqual(q, 11.0)
|
||||||
|
self.pack_location.exclude_from_immediately_usable_qty = True
|
||||||
|
self.product.invalidate_recordset() # force recompute
|
||||||
|
q = self.product.with_context(**ctx_loc).immediately_usable_qty
|
||||||
|
self.assertEqual(q, 7.0)
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!-- Copyright 2020 ACSONE SA/NV
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||||
|
<odoo>
|
||||||
|
<record model="ir.ui.view" id="stock_location_form_view">
|
||||||
|
<field name="name">stock.location.form (in
|
||||||
|
alc_stock_available_immediately)
|
||||||
|
</field>
|
||||||
|
<field name="model">stock.location</field>
|
||||||
|
<field name="inherit_id" ref="stock.view_location_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='removal_strategy_id']" position="after">
|
||||||
|
<field name="exclude_from_immediately_usable_qty" />
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="stock_location_search_view">
|
||||||
|
<field
|
||||||
|
name="name"
|
||||||
|
>stock.location.search (in alc_stock_available_immediately)</field>
|
||||||
|
<field name="model">stock.location</field>
|
||||||
|
<field name="inherit_id" ref="stock.view_location_search" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<filter name="inactive" position="after">
|
||||||
|
<filter
|
||||||
|
string="Excluded from immediately usable quantities"
|
||||||
|
name="exclude_from_immediately_usable_qty"
|
||||||
|
domain="[('exclude_from_immediately_usable_qty','=',True)]"
|
||||||
|
/>
|
||||||
|
</filter>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user