diff --git a/stock_account_quantity_history_location/__init__.py b/stock_account_quantity_history_location/__init__.py index e69de29..326c3db 100644 --- a/stock_account_quantity_history_location/__init__.py +++ b/stock_account_quantity_history_location/__init__.py @@ -0,0 +1 @@ +from . import wizards \ No newline at end of file diff --git a/stock_account_quantity_history_location/tests/__init__.py b/stock_account_quantity_history_location/tests/__init__.py new file mode 100644 index 0000000..0118859 --- /dev/null +++ b/stock_account_quantity_history_location/tests/__init__.py @@ -0,0 +1 @@ +from . import test_valuation_location diff --git a/stock_account_quantity_history_location/tests/test_valuation_location.py b/stock_account_quantity_history_location/tests/test_valuation_location.py new file mode 100644 index 0000000..7b8704d --- /dev/null +++ b/stock_account_quantity_history_location/tests/test_valuation_location.py @@ -0,0 +1,55 @@ +# Copyright 2020 Tecnativa - David Vidal +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.addons.stock_quantity_history_location.tests import ( + test_stock_quantity_history_location +) + + +class TestValuationLocation(test_stock_quantity_history_location + .TestStockQuantityHistoryLocation): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env['product.price.history'].create({ + 'datetime': '2019-08-12', + 'product_id': cls.product.id, + 'cost': 35.01, + }) + cls.env['product.price.history'].create({ + 'datetime': '2020-01-01', + 'product_id': cls.product.id, + 'cost': 33.33, + }) + cls.product.categ_id.property_cost_method = 'standard' + cls.test_stock_loc2 = cls.env['stock.location'].create({ + 'usage': 'internal', + 'name': 'Test Stock Location 2', + 'company_id': cls.main_company.id + }) + # Create a move for the past + move = cls.env['stock.move'].create({ + 'name': 'Stock move in', + 'location_id': cls.supplier_location.id, + 'location_dest_id': cls.test_stock_loc2.id, + 'product_id': cls.product.id, + 'product_uom': cls.product.uom_id.id, + 'product_uom_qty': 50.0, + }) + move._action_confirm() + move._action_assign() + move_line = move.move_line_ids[0] + move_line.qty_done = 50.0 + move._action_done() + move.date = "2020-01-01" + + def test_stock_location_valuation(self): + wizard = self.env['stock.quantity.history'].create({ + "location_id": self.test_stock_loc2.id, + "include_child_locations": True, + "compute_at_date": 1, + "date": "2020-01-01", + }) + action = wizard.with_context( + company_owned=True, valuation=True).open_table() + self.assertAlmostEqual( + self.product.with_context(action['context']).stock_value, 1666.5) diff --git a/stock_account_quantity_history_location/wizards/__init__.py b/stock_account_quantity_history_location/wizards/__init__.py new file mode 100644 index 0000000..500ceb8 --- /dev/null +++ b/stock_account_quantity_history_location/wizards/__init__.py @@ -0,0 +1,2 @@ +from . import stock_quantity_history + diff --git a/stock_account_quantity_history_location/wizards/stock_quantity_history.py b/stock_account_quantity_history_location/wizards/stock_quantity_history.py new file mode 100644 index 0000000..ec3ba8f --- /dev/null +++ b/stock_account_quantity_history_location/wizards/stock_quantity_history.py @@ -0,0 +1,36 @@ +# Copyright 2019 Eficent Business and IT Consulting Services, S.L. +# Copyright 2019 Aleph Objects, Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import ast +from odoo import models + + +class StockQuantityHistory(models.TransientModel): + _inherit = 'stock.quantity.history' + + def open_table(self): + """Stock valuation goes by a different path than stock report, so + we ensure the correct context as well""" + action = super().open_table() + if not self.env.context.get('valuation'): + return action + # Show 0 quantities on Inventory Valuation to display Account Valuation + # anomalies, such as, non 0 stock_value on cost_method FIFO + if not self.location_id: + domain = ast.literal_eval(action['domain']) + domain.pop(domain.index(('qty_available', '!=', 0))) + action['domain'] = domain + ctx = action['context'] + if isinstance(ctx, str): + ctx = ast.literal_eval(ctx) + if self.location_id: + ctx['location'] = self.location_id.id + ctx['compute_child'] = self.include_child_locations + if ctx.get('company_owned', False): + ctx.pop('company_owned') + # Ensure the context isn't added later and catch it + ctx['drop_company_owned'] = True + action['name'] = '%s (%s)' % (action['name'], + self.location_id.complete_name) + action['context'] = ctx + return action diff --git a/stock_account_quantity_history_location/wizards/stock_quantity_history.xml b/stock_account_quantity_history_location/wizards/stock_quantity_history.xml index fc09cdf..3844ef1 100644 --- a/stock_account_quantity_history_location/wizards/stock_quantity_history.xml +++ b/stock_account_quantity_history_location/wizards/stock_quantity_history.xml @@ -9,12 +9,6 @@ -
-

The accounting valuation is not calculated when you specify a location. -

-
diff --git a/stock_quantity_history_location/__init__.py b/stock_quantity_history_location/__init__.py index 5cb1c49..aee8895 100644 --- a/stock_quantity_history_location/__init__.py +++ b/stock_quantity_history_location/__init__.py @@ -1 +1,2 @@ +from . import models from . import wizards diff --git a/stock_quantity_history_location/models/__init__.py b/stock_quantity_history_location/models/__init__.py new file mode 100644 index 0000000..9649db7 --- /dev/null +++ b/stock_quantity_history_location/models/__init__.py @@ -0,0 +1 @@ +from . import product diff --git a/stock_quantity_history_location/models/product.py b/stock_quantity_history_location/models/product.py new file mode 100644 index 0000000..46445e8 --- /dev/null +++ b/stock_quantity_history_location/models/product.py @@ -0,0 +1,16 @@ +# Copyright 2019 Tecnativa - David Vidal +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import models + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + def _get_domain_locations(self): + """Ensures the location context isn't overriden""" + ctx = dict(self.env.context) + if not ctx.get('drop_company_owned') or not ctx.get('company_owned'): + return super()._get_domain_locations() + ctx.pop('company_owned', None) + self_ctx = self.with_context(ctx) + return super(ProductProduct, self_ctx)._get_domain_locations() diff --git a/stock_quantity_history_location/static/description/index.html b/stock_quantity_history_location/static/description/index.html index 3590484..87088e3 100644 --- a/stock_quantity_history_location/static/description/index.html +++ b/stock_quantity_history_location/static/description/index.html @@ -367,7 +367,7 @@ ul.auto-toc { !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/stock-logistics-reporting Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/stock-logistics-reporting Translate me on Weblate Try me on Runbot

This module allows to run an Inventory report or Inventory Valuation report by location, for a past date or for current date.

Table of contents

@@ -404,7 +404,7 @@ report by location, for a past date or for current date.

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -422,7 +422,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome

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/stock-logistics-reporting project on GitHub.

+

This module is part of the OCA/stock-logistics-reporting project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/stock_quantity_history_location/tests/test_stock_quantity_history_location.py b/stock_quantity_history_location/tests/test_stock_quantity_history_location.py index 59cedea..56d6a67 100644 --- a/stock_quantity_history_location/tests/test_stock_quantity_history_location.py +++ b/stock_quantity_history_location/tests/test_stock_quantity_history_location.py @@ -9,14 +9,68 @@ class TestStockQuantityHistoryLocation(SavepointCase): @classmethod def setUpClass(cls): super(TestStockQuantityHistoryLocation, cls).setUpClass() - cls.stock_loc = cls.env.ref('stock.stock_location_stock') + cls.supplier_location = cls.env.ref('stock.stock_location_suppliers') + cls.main_company = cls.env.ref('base.main_company') + cls.product = cls.env.ref('product.product_product_3') + cls.test_stock_loc = cls.env['stock.location'].create({ + 'usage': 'internal', + 'name': 'Test Stock Location', + 'company_id': cls.main_company.id + }) + cls.child_test_stock_loc = cls.env['stock.location'].create({ + 'usage': 'internal', + 'name': 'Child Test Stock Location', + 'location_id': cls.test_stock_loc.id, + 'company_id': cls.main_company.id + }) + # Create a move for the past + move = cls.env['stock.move'].create({ + 'name': 'Stock move in', + 'location_id': cls.supplier_location.id, + 'location_dest_id': cls.child_test_stock_loc.id, + 'product_id': cls.product.id, + 'product_uom': cls.product.uom_id.id, + 'product_uom_qty': 100.0, + }) + move._action_confirm() + move._action_assign() + move_line = move.move_line_ids[0] + move_line.qty_done = 100.0 + move._action_done() + move.date = "2019-08-11" - def test_wizard(self): - self.wizard = self.env['stock.quantity.history'].create({ - "location_id": self.stock_loc.id, + +class StockQuantityHistoryLocationTests(TestStockQuantityHistoryLocation): + + def test_wizard_past_date(self): + wizard = self.env['stock.quantity.history'].create({ + "location_id": self.test_stock_loc.id, + "include_child_locations": True, + "compute_at_date": 1, + "date": "2019-08-12", + }) + action = wizard.with_context(company_owned=True).open_table() + self.assertEquals( + self.product.with_context(action['context']).qty_available, 100.0) + self.assertEquals(self.product.with_context( + location=self.child_test_stock_loc.id, + to_date="2019-08-10").qty_available, 0.0) + + def test_wizard_current(self): + wizard = self.env['stock.quantity.history'].create({ + "location_id": self.test_stock_loc.id, + "include_child_locations": False, + "compute_at_date": 0, + }) + action = wizard.with_context().open_table() + self.assertEquals(action['domain'], + [('location_id', '=', self.test_stock_loc.id)]) + wizard = self.env['stock.quantity.history'].create({ + "location_id": self.test_stock_loc.id, "include_child_locations": True, "compute_at_date": 0, - "company_owned": True }) - wizard = self.wizard.open_table() - self.assertEquals(wizard['context']['location'], self.stock_loc.id) + action = wizard.with_context().open_table() + self.assertEquals(action['domain'], + [('location_id', 'child_of', + self.test_stock_loc.id)]) diff --git a/stock_quantity_history_location/wizards/stock_quantity_history.py b/stock_quantity_history_location/wizards/stock_quantity_history.py index 689ee4f..30818fa 100644 --- a/stock_quantity_history_location/wizards/stock_quantity_history.py +++ b/stock_quantity_history_location/wizards/stock_quantity_history.py @@ -20,12 +20,21 @@ class StockQuantityHistory(models.TransientModel): ctx = action['context'] if isinstance(ctx, str): ctx = ast.literal_eval(ctx) - action['domain'] = [('type', '=', 'product')] - if self.location_id: + # If we are opening the current quants, filter by domain + if self.location_id and not self.compute_at_date and not \ + self.env.context.get('valuation'): + if self.include_child_locations: + action['domain'] = [ + ('location_id', 'child_of', self.location_id.id)] + else: + action['domain'] = [('location_id', '=', self.location_id.id)] + elif self.location_id: ctx['location'] = self.location_id.id ctx['compute_child'] = self.include_child_locations if ctx.get('company_owned', False): ctx.pop('company_owned') + # Ensure the context isn't added later and catch it + ctx['drop_company_owned'] = True action['name'] = '%s (%s)' % (action['name'], self.location_id.complete_name) action['context'] = ctx