[16.0][ADD] stock_available_immediately_exclude_location

This commit is contained in:
hda
2023-01-18 11:24:04 +01:00
committed by Sébastien Alix
parent ffbfd6f16f
commit c5ff802952
13 changed files with 254 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
==================================================
Exclude locations from immediately usable quantity
==================================================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

View File

@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

View 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,
}

View File

@@ -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 ""

View File

@@ -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

View File

@@ -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)]]
)

View File

@@ -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",
)

View File

@@ -0,0 +1 @@
* Author: Hughes Damry <hughes.damry@acsone.eu>

View File

@@ -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

View File

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

View File

@@ -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)

View File

@@ -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>