← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~camptocamp/product-kitting/7.0-fix_bom_stock-afe into lp:product-kitting

 

Alexandre Fayolle - camptocamp has proposed merging lp:~camptocamp/product-kitting/7.0-fix_bom_stock-afe into lp:product-kitting.

Requested reviews:
  Product Core Editors (product-core-editors)
Related bugs:
  Bug #1279351 in Product - Kitting Management: "bom_stock: the quantity produced by the BOM is ignored"
  https://bugs.launchpad.net/product-kitting/+bug/1279351
  Bug #1279355 in Product - Kitting Management: "mrp_bom: missing dependency on mrp"
  https://bugs.launchpad.net/product-kitting/+bug/1279355
  Bug #1279383 in Product - Kitting Management: "bom_stock: wrong computed stock if BOM uses UOM which are different from product UOM"
  https://bugs.launchpad.net/product-kitting/+bug/1279383

For more details, see:
https://code.launchpad.net/~camptocamp/product-kitting/7.0-fix_bom_stock-afe/+merge/205988

fix bom_stock issues

* reformat to 7.0 standards
* missing dependency on mrp
* use bom produced qty 
* fix issues when the uom in the BOM are different from product UOM
-- 
https://code.launchpad.net/~camptocamp/product-kitting/7.0-fix_bom_stock-afe/+merge/205988
Your team Product Core Editors is requested to review the proposed merge of lp:~camptocamp/product-kitting/7.0-fix_bom_stock-afe into lp:product-kitting.
=== modified file 'bom_stock/__openerp__.py'
--- bom_stock/__openerp__.py	2012-02-22 10:06:26 +0000
+++ bom_stock/__openerp__.py	2014-02-12 15:38:39 +0000
@@ -24,15 +24,23 @@
     'category': 'Generic Modules/Others',
     'description':
      """Compute the BOM  stock Value. BoM Stock Value are computed by:
-      "(Reference stock" of "Product" + How much could I produce of That "Product" according to the component's "Reference Stock)"
-      "This reference stock can be chosen by company through a selection field and can be one of the available stock quantity computed in the system : Available stock, Virtual stock, immediately_usable stock (from stock_available_immediately)".""" 
+      (`Reference stock` of `Product` + How much could I produce of that `Product` according to the component's `Reference Stock`)
+
+      This reference stock can be chosen by company through a selection field
+      and can be one of the available stock quantity computed in the system :
+      Available stock, Virtual stock, immediately_usable stock (from
+      stock_available_immediately)."""
     ,
     'author': 'Camptocamp',
     'website': 'http://www.camptocamp.com',
-    'depends': ['stock', 'stock_available_immediately'],
-    'init_xml': [],
-    'update_xml': ['bom_stock_view.xml'],
-    'demo_xml': [],
+    'depends': ['stock',
+                'mrp',
+                'stock_available_immediately',
+                ],
+    'data': ['bom_stock_view.xml'],
+    'demo': [],
+    'test': ['tests/test_bom_stock.yml',
+             ],
     'installable': True,
     'active': False,
 }

=== modified file 'bom_stock/bom_stock.py'
--- bom_stock/bom_stock.py	2012-03-14 16:27:05 +0000
+++ bom_stock/bom_stock.py	2014-02-12 15:38:39 +0000
@@ -18,34 +18,31 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ##############################################################################
-import decimal_precision as dp
-
-from osv import fields, osv
-
-
-class res_company(osv.osv):
-
+from openerp.osv import fields, orm
+
+from openerp.addons import decimal_precision as dp
+
+
+class res_company(orm.Model):
     _inherit = 'res.company'
-
     _columns = {
         'ref_stock': fields.selection(
             [('real', 'Real Stock'),
              ('virtual', 'Virtual Stock'),
              ('immediately', 'Immediately Usable Stock')],
             'Reference Stock for BoM Stock')
-    }
+        }
 
     _defaults = {
-        'ref_stock': lambda *a: 'real'
-    }
-
-res_company()
-
-
-class product_bom_stock_value(osv.osv):
-    """
-    Inherit Product in order to add an "Bom Stock" field
-    """
+        'ref_stock': 'real',
+        }
+
+
+class product_product(orm.Model):
+    """
+    Inherit Product in order to add a "BOM Stock" field
+    """
+    _inherit = 'product.product'
 
     def _bom_stock_mapping(self, cr, uid, context=None):
         return {'real': 'qty_available',
@@ -54,8 +51,8 @@
 
     def _compute_bom_stock(self, cr, uid, product,
                            quantities, company, context=None):
-        bom_obj = self.pool.get('mrp.bom')
-
+        bom_obj = self.pool['mrp.bom']
+        uom_obj = self.pool['product.uom']
         mapping = self._bom_stock_mapping(cr, uid, context=context)
         stock_field = mapping[company.ref_stock]
 
@@ -73,17 +70,17 @@
                 # get the minimal number of items we can produce with them
                 for line in bom.bom_lines:
                     prod_min_quantity = 0.0
-                    bom_qty = line.product_id[stock_field]
-
+                    bom_qty = line.product_id[stock_field] # expressed in product UOM
                     # the reference stock of the component must be greater
                     # than the quantity of components required to
                     # build the bom
-                    if bom_qty >= line.product_qty:
-                        prod_min_quantity = (
-                            (bom_qty *
-                             line.product_id.uom_id.factor /
-                             line.product_uom.factor) /
-                            line.product_qty)  # line.product_qty is always > 0
+                    line_product_qty = uom_obj._compute_qty_obj(cr, uid,
+                                                                line.product_uom,
+                                                                line.product_qty,
+                                                                line.product_id.uom_id,
+                                                                context=context)
+                    if bom_qty >= line_product_qty:
+                        prod_min_quantity = bom_qty / line_product_qty  # line.product_qty is always > 0
                     else:
                         # if one product has not enough stock,
                         # we do not need to compute next lines
@@ -91,11 +88,14 @@
                         stop_compute_bom = True
 
                     prod_min_quantities.append(prod_min_quantity)
-
                     if stop_compute_bom:
                         break
-
-            product_qty += min(prod_min_quantities)
+            produced_qty = uom_obj._compute_qty_obj(cr, uid,
+                                                    bom.product_uom,
+                                                    bom.product_qty,
+                                                    bom.product_id.uom_id,
+                                                    context=context)
+            product_qty += min(prod_min_quantities) * produced_qty
         return product_qty
 
     def _product_available(self, cr, uid, ids, field_names=None,
@@ -103,14 +103,14 @@
         # We need available, virtual or immediately usable
         # quantity which is selected from company to compute Bom stock Value
         # so we add them in the calculation.
-        user_obj = self.pool.get('res.users')
-        comp_obj = self.pool.get('res.company')
+        user_obj = self.pool['res.users']
+        comp_obj = self.pool['res.company']
         if 'bom_stock' in field_names:
             field_names.append('qty_available')
             field_names.append('immediately_usable_qty')
             field_names.append('virtual_available')
 
-        res = super(product_bom_stock_value, self)._product_available(
+        res = super(product_product, self)._product_available(
             cr, uid, ids, field_names, arg, context)
 
         if 'bom_stock' in field_names:
@@ -126,7 +126,6 @@
                         cr, uid, product, stock_qty, company, context=context)
         return res
 
-    _inherit = 'product.product'
 
     _columns = {
         'qty_available': fields.function(
@@ -221,6 +220,4 @@
                  "how much could I produce of this product with the BoM"
                  "Components",
             multi='qty_available'),
-    }
-
-product_bom_stock_value()
+        }

=== modified file 'bom_stock/bom_stock_view.xml'
--- bom_stock/bom_stock_view.xml	2012-03-14 16:27:05 +0000
+++ bom_stock/bom_stock_view.xml	2014-02-12 15:38:39 +0000
@@ -9,10 +9,10 @@
             <field name="arch" type="xml">
                 <field name="immediately_usable_qty" position="after">
                     <field name="bom_stock" />
-                </field>   
+                </field>
             </field>
         </record>
-        
+
         <record model="ir.ui.view" id="view_reference_stock_company_form">
             <field name="name">res.company.reference.stock.form.inherit</field>
             <field name="model">res.company</field>
@@ -22,7 +22,7 @@
                 <page string="Configuration" position="inside">
                     <separator string="Stock - Various" colspan="4"/>
                     <field name="ref_stock" />
-                </page>   
+                </page>
             </field>
         </record>
 

=== added directory 'bom_stock/tests'
=== added file 'bom_stock/tests/test_bom_stock.yml'
--- bom_stock/tests/test_bom_stock.yml	1970-01-01 00:00:00 +0000
+++ bom_stock/tests/test_bom_stock.yml	2014-02-12 15:38:39 +0000
@@ -0,0 +1,54 @@
+-
+  I create a product "Pipe"
+-
+  !record {model: product.product, id: product1}:
+    name: Pipe
+    type: product
+    supply_method: buy
+-
+  I create a product "Half Pipe"
+-
+  !record {model: product.product, id: product2}:
+    name: Half Pipe
+    type: product
+    supply_method: produce
+-
+  I explain how to build Half Pipes
+-
+  !record {model: mrp.bom, id: bom_prod2}:
+    name: half pipe
+    product_id: product2
+    product_qty: 2
+    product_uom: product.product_uom_dozen
+    bom_lines:
+      - product_id: product1
+        product_qty: 1
+        product_uom: product.product_uom_dozen
+-
+  I create stock of Pipes
+-
+  !record {model: stock.move, id: move1}:
+    product_id: product1
+    product_qty: 12
+    product_uom: product.product_uom_unit
+    location_id: stock.location_inventory
+    location_dest_id: stock.stock_location_stock
+-
+  I create stock of Half Pipes
+-
+  !record {model: stock.move, id: move2}:
+    product_id: product2
+    product_qty: 1
+    product_uom: product.product_uom_unit
+    location_id: stock.location_inventory
+    location_dest_id: stock.stock_location_stock
+-
+  !python {model: stock.move}: |
+    move_ids = [ref("move1"), ref("move2")]
+    self.action_done(cr, uid, move_ids)
+-
+  I check the stock level of half pipes, which should be 1 (existing stock) + 2x12
+-
+  !assert {model: product.product, id: product2}:
+    - bom_stock == 25
+


Follow ups