Merge lp:~acsone-openerp/stock-logistic-warehouse/7.0-inventory-hierarchical-fill-lga into lp:~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-hierarchical

Proposed by Laetitia Gangloff (Acsone)
Status: Superseded
Proposed branch: lp:~acsone-openerp/stock-logistic-warehouse/7.0-inventory-hierarchical-fill-lga
Merge into: lp:~numerigraphe-team/stock-logistic-warehouse/7.0-inventory-hierarchical
Diff against target: 343 lines (+259/-14)
8 files modified
stock_inventory_hierarchical_location/__openerp__.py (+1/-1)
stock_inventory_hierarchical_location/inventory_hierarchical_location.py (+19/-9)
stock_inventory_hierarchical_location/inventory_hierarchical_location_view.xml (+1/-1)
stock_inventory_hierarchical_location/tests/__init__.py (+39/-0)
stock_inventory_hierarchical_location/tests/fill_inventory_test.py (+117/-0)
stock_inventory_hierarchical_location/wizard/__init__.py (+1/-0)
stock_inventory_hierarchical_location/wizard/stock_fill_location_inventory.py (+76/-0)
stock_inventory_location/stock_inventory_location.py (+5/-3)
To merge this branch: bzr merge lp:~acsone-openerp/stock-logistic-warehouse/7.0-inventory-hierarchical-fill-lga
Reviewer Review Type Date Requested Status
Lionel Sausin - Initiatives/Numérigraphe has conflicts Needs Fixing
Review via email: mp+222965@code.launchpad.net

This proposal has been superseded by a proposal from 2014-06-12.

Description of the change

I make some change in the module stock_inventory_hierarchical_location.

The goal is to take account of sub-inventories in case of an exhaustive inventory in two case :
-confirm inventory
-fill inventory

To post a comment you must log in.
Revision history for this message
Lionel Sausin - Initiatives/Numérigraphe (ls-initiatives) wrote :

Thanks for your help.
I've just merged our own fixes of the day, will you please merge them to avoid conflicts ?

I think I understand what you're trying to do in fill_inventory and it's not exactly how we had it in v6 - which is broken right now in v7, and would require a patch on the code addons.
Your patch completely excludes the locations of sub-inventories, whereas we used to only exclude the generated inventory lines. That would allow us to "catch" the lines that could have been missing from sub-inventories, but since they're exhaustive anyway there should not be any.
So I guess your approach is correct.
I'll let Loïc decide, he's working on the problem too.

review: Needs Resubmitting (has conflicts)
Revision history for this message
Lionel Sausin - Initiatives/Numérigraphe (ls-initiatives) :
review: Needs Fixing (has conflicts)

Unmerged revisions

39. By Laetitia Gangloff (Acsone)

stock_inventory_hierarchical_location: to fill inventory, check if it is an exhaustive fill to define if location should be exclude

38. By Laetitia Gangloff (Acsone)

stock_inventory_hierarchical_location: use sub-inventories to determine missing locations and to fill inventory with the fill_inventory wizard - move test in tests and add some python test for the previous issue / stock_inventory_location: correct a mysterious problem that hapenned when many inventory ids are passed

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'stock_inventory_hierarchical_location/__openerp__.py'
--- stock_inventory_hierarchical_location/__openerp__.py 2014-06-10 14:04:38 +0000
+++ stock_inventory_hierarchical_location/__openerp__.py 2014-06-12 15:33:45 +0000
@@ -43,6 +43,6 @@
43 "data": [43 "data": [
44 "inventory_hierarchical_location_view.xml",44 "inventory_hierarchical_location_view.xml",
45 ],45 ],
46 "test": ["test/inventory_hierarchical_location_test.yml"],46 "test": ["tests/inventory_hierarchical_location_test.yml"],
47 "demo": ["inventory_hierarchical_location_demo.xml"],47 "demo": ["inventory_hierarchical_location_demo.xml"],
48}48}
4949
=== modified file 'stock_inventory_hierarchical_location/inventory_hierarchical_location.py'
--- stock_inventory_hierarchical_location/inventory_hierarchical_location.py 2014-06-10 14:09:03 +0000
+++ stock_inventory_hierarchical_location/inventory_hierarchical_location.py 2014-06-12 15:33:45 +0000
@@ -44,6 +44,25 @@
44 return super(HierarchicalExhInventory, self).action_open(44 return super(HierarchicalExhInventory, self).action_open(
45 cr, uid, ids, context=context)45 cr, uid, ids, context=context)
4646
47 def _get_all_sub_inventories(self, cr, uid, ids, res, context=None):
48 """Get the list of all sub inventories of a list inventories
49 """
50 for inventory in self.browse(cr, uid, ids, context=context):
51 for i in inventory.inventory_ids:
52 res.append(i.id)
53 self._get_all_sub_inventories(cr, uid, [i.id], res, context)
54 return res
55
56 def get_missing_locations(self, cr, uid, ids, context=None):
57 """Compute the list of location_ids which are missing from the lines
58
59 Here, "missing" means the location is the inventory's location or one
60 of it's children, and the inventory or a sub-inventory does not contain
61 any line with this location."""
62 # remove location of sub inventory
63 inventory_ids = self._get_all_sub_inventories(cr, uid, ids, ids, context=context)
64 return super(HierarchicalExhInventory, self).get_missing_locations(cr, uid, inventory_ids, context=context)
65
47 # TODO v8: probably only keep the state "done"66 # TODO v8: probably only keep the state "done"
48 def confirm_missing_locations(self, cr, uid, ids, context=None):67 def confirm_missing_locations(self, cr, uid, ids, context=None):
49 """Do something only if children state are confirm or done."""68 """Do something only if children state are confirm or done."""
@@ -80,12 +99,3 @@
80 }99 }
81 return {}100 return {}
82101
83 def _fill_location_lines(self, cr, uid, inventory_id, location_ids,
84 set_stock_zero, context=None):
85 """Add ids of children inventory into list """
86 children_inventory_ids = self.search(
87 cr, uid, [('parent_id', 'child_of', inventory_id)])
88 context['children_inventory_ids'] = children_inventory_ids
89 return super(HierarchicalExhInventory, self)._fill_location_lines(
90 cr, uid, inventory_id, location_ids, set_stock_zero,
91 context=context)
92102
=== modified file 'stock_inventory_hierarchical_location/inventory_hierarchical_location_view.xml'
--- stock_inventory_hierarchical_location/inventory_hierarchical_location_view.xml 2014-06-11 15:02:33 +0000
+++ stock_inventory_hierarchical_location/inventory_hierarchical_location_view.xml 2014-06-12 15:33:45 +0000
@@ -5,7 +5,7 @@
5 <record model="ir.ui.view" id="stock_inventory_hierarchical_location_form_view">5 <record model="ir.ui.view" id="stock_inventory_hierarchical_location_form_view">
6 <field name="name">hierarchical.inventory.location.form</field>6 <field name="name">hierarchical.inventory.location.form</field>
7 <field name="model">stock.inventory</field>7 <field name="model">stock.inventory</field>
8 <field name="inherit_id" ref="stock.view_inventory_form" />8 <field name="inherit_id" ref="stock_inventory_hierarchical.stock_inventory_hierarchical_form_view" />
9 <field name="arch" type="xml">9 <field name="arch" type="xml">
10 <xpath expr="/form//field[@name='exhaustive']" position="attributes">10 <xpath expr="/form//field[@name='exhaustive']" position="attributes">
11 <attribute name="attrs">{'readonly':[('parent_id', '!=', False)]}</attribute>11 <attribute name="attrs">{'readonly':[('parent_id', '!=', False)]}</attribute>
1212
=== renamed directory 'stock_inventory_hierarchical_location/test' => 'stock_inventory_hierarchical_location/tests'
=== added file 'stock_inventory_hierarchical_location/tests/__init__.py'
--- stock_inventory_hierarchical_location/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_inventory_hierarchical_location/tests/__init__.py 2014-06-12 15:33:45 +0000
@@ -0,0 +1,39 @@
1# -*- coding: utf-8 -*-
2#
3#
4# Authors: Laetitia Gangloff
5# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
6# All Rights Reserved
7#
8# WARNING: This program as such is intended to be used by professional
9# programmers who take the whole responsibility of assessing all potential
10# consequences resulting from its eventual inadequacies and bugs.
11# End users who are looking for a ready-to-use solution with commercial
12# guarantees and support are strongly advised to contact a Free Software
13# Service Company.
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU Affero General Public License as
17# published by the Free Software Foundation, either version 3 of the
18# License, or (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU Affero General Public License for more details.
24#
25# You should have received a copy of the GNU Affero General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
27#
28#
29
30import fill_inventory_test
31
32fast_suite = [
33]
34
35checks = [
36 fill_inventory_test,
37]
38
39# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
040
=== added file 'stock_inventory_hierarchical_location/tests/fill_inventory_test.py'
--- stock_inventory_hierarchical_location/tests/fill_inventory_test.py 1970-01-01 00:00:00 +0000
+++ stock_inventory_hierarchical_location/tests/fill_inventory_test.py 2014-06-12 15:33:45 +0000
@@ -0,0 +1,117 @@
1# -*- coding: utf-8 -*-
2#
3#
4# Authors: Laetitia Gangloff
5# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
6# All Rights Reserved
7#
8# WARNING: This program as such is intended to be used by professional
9# programmers who take the whole responsibility of assessing all potential
10# consequences resulting from its eventual inadequacies and bugs.
11# End users who are looking for a ready-to-use solution with commercial
12# guarantees and support are strongly advised to contact a Free Software
13# Service Company.
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU Affero General Public License as
17# published by the Free Software Foundation, either version 3 of the
18# License, or (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU Affero General Public License for more details.
24#
25# You should have received a copy of the GNU Affero General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
27#
28#
29
30import openerp.tests.common as common
31
32DB = common.DB
33ADMIN_USER_ID = common.ADMIN_USER_ID
34
35
36class fill_inventory_test(common.TransactionCase):
37
38 def setUp(self):
39 super(fill_inventory_test, self).setUp()
40
41 def test_missing_location(self):
42 """
43 Test that when confirm a parent inventory, the child location are not in the confirmation result
44 """
45 parent_inventory_id = self.ref('stock_inventory_hierarchical_location.parent_inventory_location')
46 self.registry('stock.inventory').action_open(self.cr, self.uid, [parent_inventory_id])
47 # confirm shelf 1 inventory
48 inventory_id = self.ref('stock_inventory_hierarchical_location.child_1_id')
49 self.registry('stock.inventory').action_open(self.cr, self.uid, [inventory_id])
50 missing_location = self.registry('stock.inventory').get_missing_locations(self.cr, self.uid, [inventory_id])
51 self.assertEqual(len(missing_location), 1, "1 missing location should be find, because the inventory is empty")
52 wizard_id = self.registry('stock.inventory.uninventoried.locations').create(self.cr, self.uid, {}, context={'active_ids': [inventory_id]})
53 self.registry('stock.inventory.uninventoried.locations').confirm_uninventoried_locations(self.cr, self.uid, wizard_id, context={'active_ids': [inventory_id]})
54 missing_location = self.registry('stock.inventory').get_missing_locations(self.cr, self.uid, [inventory_id])
55 self.assertEqual(len(missing_location), 0, "No missing location should be find, because the inventory is confirmed")
56 # confirm shelf 2 inventory
57 inventory_id = self.ref('stock_inventory_hierarchical_location.child_2_id')
58 self.registry('stock.inventory').action_open(self.cr, self.uid, [inventory_id])
59 missing_location = self.registry('stock.inventory').get_missing_locations(self.cr, self.uid, [inventory_id])
60 self.assertEqual(len(missing_location), 1, "1 missing location should be fine, because the inventory is empty")
61 self.registry('stock.inventory.line').create(self.cr, self.uid, {'product_id': self.ref('product.product_product_7'),
62 'product_uom': self.ref('product.product_uom_unit'),
63 'company_id': self.ref('base.main_company'),
64 'inventory_id': inventory_id,
65 'product_qty': 18.0,
66 'location_id': self.ref('stock.stock_location_14')})
67 missing_location = self.registry('stock.inventory').get_missing_locations(self.cr, self.uid, [inventory_id])
68 self.assertEqual(len(missing_location), 0, "No missing location should be find, because the inventory is filled")
69 wizard_id = self.registry('stock.inventory.uninventoried.locations').create(self.cr, self.uid, {}, context={'active_ids': [inventory_id]})
70 wizard = self.registry('stock.inventory.uninventoried.locations').browse(self.cr, self.uid, wizard_id, context={'active_ids': [inventory_id]})
71 self.assertEqual(len(wizard.location_ids), 0, "The wizard should not contain any lines but contains %s." % wizard.location_ids)
72 self.registry('stock.inventory.uninventoried.locations').confirm_uninventoried_locations(self.cr, self.uid, wizard_id, context={'active_ids': [inventory_id]})
73 # confirm parent inventory
74 missing_location = self.registry('stock.inventory').get_missing_locations(self.cr, self.uid, [parent_inventory_id])
75 self.assertEqual(len(missing_location), 1, "Only 1 missing location should be find, because there is some location in child inventory")
76
77 def test_fill_inventory(self):
78 """
79 Test that when fill a parent inventory, the child location are not in the result
80 """
81 parent_inventory_id = self.ref('stock_inventory_hierarchical_location.parent_inventory_location')
82 self.registry('stock.inventory').action_open(self.cr, self.uid, [parent_inventory_id])
83 # confirm shelf 1 inventory
84 inventory_id = self.ref('stock_inventory_hierarchical_location.child_1_id')
85 self.registry('stock.inventory').action_open(self.cr, self.uid, [inventory_id])
86 wizard_id = self.registry('stock.fill.inventory').create(self.cr, self.uid, {'location_id': self.ref('stock.stock_location_components'),
87 'recursive': True,
88 'exhaustive': True,
89 'set_stock_zero': True}, context={'active_ids': [inventory_id]})
90 self.registry('stock.fill.inventory').fill_inventory(self.cr, self.uid, [wizard_id], context={'active_ids': [inventory_id]})
91 inventory_line_ids = self.registry('stock.inventory.line').search(self.cr, self.uid, [('inventory_id', '=', inventory_id)])
92 self.assertEqual(len(inventory_line_ids), 12, "12 inventory line is fount after filling inventory")
93 # confirm shelf 2 inventory
94 inventory_id = self.ref('stock_inventory_hierarchical_location.child_2_id')
95 self.registry('stock.inventory').action_open(self.cr, self.uid, [inventory_id])
96 wizard_id = self.registry('stock.fill.inventory').create(self.cr, self.uid, {'location_id': self.ref('stock.stock_location_14'),
97 'recursive': True,
98 'exhaustive': True,
99 'set_stock_zero': True}, context={'active_ids': [inventory_id]})
100 self.registry('stock.fill.inventory').fill_inventory(self.cr, self.uid, [wizard_id], context={'active_ids': [inventory_id]})
101 inventory_line_ids = self.registry('stock.inventory.line').search(self.cr, self.uid, [('inventory_id', '=', inventory_id)])
102 self.assertEqual(len(inventory_line_ids), 4, "1 inventory line is fount after filling inventory")
103 # confirm parent inventory
104 wizard_id = self.registry('stock.fill.inventory').create(self.cr, self.uid, {'location_id': self.ref('stock.stock_location_stock'),
105 'recursive': True,
106 'exhaustive': True,
107 'set_stock_zero': True}, context={'active_ids': [parent_inventory_id]})
108 try:
109 self.registry('stock.fill.inventory').fill_inventory(self.cr, self.uid, [wizard_id], context={'active_ids': [parent_inventory_id]})
110 except Exception:
111 exception_happened = True
112 pass
113 self.assertTrue(exception_happened)
114 inventory_line_ids = self.registry('stock.inventory.line').search(self.cr, self.uid, [('inventory_id', '=', parent_inventory_id)])
115 self.assertEqual(len(inventory_line_ids), 0, "No inventory line is fount after filling inventory")
116
117# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
0118
=== modified file 'stock_inventory_hierarchical_location/wizard/__init__.py'
--- stock_inventory_hierarchical_location/wizard/__init__.py 2014-04-02 10:04:21 +0000
+++ stock_inventory_hierarchical_location/wizard/__init__.py 2014-06-12 15:33:45 +0000
@@ -19,3 +19,4 @@
19##############################################################################19##############################################################################
2020
21import stock_confirm_uninventoried_location21import stock_confirm_uninventoried_location
22from . import stock_fill_location_inventory
2223
=== added file 'stock_inventory_hierarchical_location/wizard/stock_fill_location_inventory.py'
--- stock_inventory_hierarchical_location/wizard/stock_fill_location_inventory.py 1970-01-01 00:00:00 +0000
+++ stock_inventory_hierarchical_location/wizard/stock_fill_location_inventory.py 2014-06-12 15:33:45 +0000
@@ -0,0 +1,76 @@
1# -*- coding: utf-8 -*-
2#
3#
4# Authors: Laetitia Gangloff
5# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
6# All Rights Reserved
7#
8# WARNING: This program as such is intended to be used by professional
9# programmers who take the whole responsibility of assessing all potential
10# consequences resulting from its eventual inadequacies and bugs.
11# End users who are looking for a ready-to-use solution with commercial
12# guarantees and support are strongly advised to contact a Free Software
13# Service Company.
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU Affero General Public License as
17# published by the Free Software Foundation, either version 3 of the
18# License, or (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU Affero General Public License for more details.
24#
25# You should have received a copy of the GNU Affero General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
27#
28#
29
30from openerp.osv import orm
31
32
33class FillInventoryWizard(orm.TransientModel):
34 """If inventory as sub inventories, do not fill with sub inventories location"""
35 _inherit = 'stock.fill.inventory'
36
37 def fill_inventory(self, cr, uid, ids, context=None):
38 """ To Import stock inventory according to products available in the location and not already in a sub inventory
39
40 We split fill_inventory on many fill_inventory (one for each location)
41 @param self: The object pointer.
42 @param cr: A database cursor
43 @param uid: ID of the user currently logged in
44 @param ids: the ID or list of IDs if we want more than one
45 @param context: A standard dictionary
46 @return:
47 """
48 if context is None:
49 context = {}
50
51 if ids and len(ids):
52 ids = ids[0]
53 else:
54 return {'type': 'ir.actions.act_window_close'}
55 fill_inventory = self.browse(cr, uid, ids, context=context)
56 if fill_inventory.recursive and fill_inventory.exhaustive:
57 exclude_location_ids = []
58 for i in self.pool['stock.inventory'].browse(cr, uid, context['active_ids']):
59 for sub_inventory in i.inventory_ids:
60 # exclude these location
61 exclude_location_ids.append(sub_inventory.location_id.id)
62 location_ids = self.pool['stock.location'].search(cr, uid,
63 [('location_id', 'child_of', [fill_inventory.location_id.id]),
64 '!', ('location_id', 'child_of', exclude_location_ids)],
65 order="id",
66 context=context)
67 for location_id in location_ids:
68 super(FillInventoryWizard, self).fill_inventory(cr, uid,
69 [self.copy(cr, uid, ids, {'location_id': location_id,
70 'recursive': False, }, context=context)],
71 context=context)
72 return {'type': 'ir.actions.act_window_close'}
73 else:
74 return super(FillInventoryWizard, self).fill_inventory(cr, uid, [ids], context=context)
75
76# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
077
=== modified file 'stock_inventory_location/stock_inventory_location.py'
--- stock_inventory_location/stock_inventory_location.py 2014-06-11 15:01:17 +0000
+++ stock_inventory_location/stock_inventory_location.py 2014-06-12 15:33:45 +0000
@@ -195,9 +195,11 @@
195 ('location_id', 'child_of', inv_location_ids),195 ('location_id', 'child_of', inv_location_ids),
196 ('usage', '=', 'internal')], context=context))196 ('usage', '=', 'internal')], context=context))
197 # Find the locations already recorded in inventory lines197 # Find the locations already recorded in inventory lines
198 line_locations_ids = set([l.location_id.id198 line_locations_ids = set()
199 for l in i.inventory_line_id199 for i in inventories:
200 for i in inventories])200 for l in i.inventory_line_id:
201 line_locations_ids.add(l.location_id.id)
202
201 return list(inv_location_ids - line_locations_ids)203 return list(inv_location_ids - line_locations_ids)
202204
203 def confirm_missing_locations(self, cr, uid, ids, context=None):205 def confirm_missing_locations(self, cr, uid, ids, context=None):

Subscribers

People subscribed via source and target branches