[FIX] mrp: bom properties
The bom related to the product in a sale line order must be filtered by the function _bom_find. If two boms can be applied on a product, the bom with the smallest sequence is applied. opw:632558
This commit is contained in:
parent
1062905acb
commit
5b479e6114
|
@ -232,16 +232,16 @@ class mrp_bom(osv.osv):
|
|||
domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATE_FORMAT)),
|
||||
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT))]
|
||||
# order to prioritize bom with product_id over the one without
|
||||
ids = self.search(cr, uid, domain, order='product_id', context=context)
|
||||
ids = self.search(cr, uid, domain, order='sequence, product_id', context=context)
|
||||
# Search a BoM which has all properties specified, or if you can not find one, you could
|
||||
# pass a BoM without any properties
|
||||
# pass a BoM without any properties with the smallest sequence
|
||||
bom_empty_prop = False
|
||||
for bom in self.pool.get('mrp.bom').browse(cr, uid, ids, context=context):
|
||||
if not set(map(int, bom.property_ids or [])) - set(properties or []):
|
||||
if properties and not bom.property_ids:
|
||||
bom_empty_prop = bom.id
|
||||
else:
|
||||
if not properties or bom.property_ids:
|
||||
return bom.id
|
||||
elif not bom_empty_prop:
|
||||
bom_empty_prop = bom.id
|
||||
return bom_empty_prop
|
||||
|
||||
def _bom_explode(self, cr, uid, bom, product, factor, properties=None, level=0, routing_id=False, previous_products=None, master_bom=None, context=None):
|
||||
|
|
|
@ -503,7 +503,7 @@
|
|||
<field name="name">PC Assemble + 512MB RAM</field>
|
||||
<field name="product_tmpl_id" ref="product.product_product_3_product_template"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="sequence">5</field>
|
||||
<field name="sequence">4</field>
|
||||
<field name="routing_id" ref="mrp_routing_2"/>
|
||||
<field name="type">phantom</field>
|
||||
</record>
|
||||
|
|
|
@ -43,38 +43,26 @@ class StockMove(osv.osv):
|
|||
if move.raw_material_production_id and move.location_dest_id.usage == 'production' and move.raw_material_production_id.product_id.track_production and not move.consumed_for:
|
||||
raise osv.except_osv(_('Warning!'), _("Because the product %s requires it, you must assign a serial number to your raw material %s to proceed further in your production. Please use the 'Produce' button to do so.") % (move.raw_material_production_id.product_id.name, move.product_id.name))
|
||||
|
||||
def _check_phantom_bom(self, cr, uid, move, context=None):
|
||||
"""check if product associated to move has a phantom bom
|
||||
return list of ids of mrp.bom for that product """
|
||||
user_company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
|
||||
#doing the search as SUPERUSER because a user with the permission to write on a stock move should be able to explode it
|
||||
#without giving him the right to read the boms.
|
||||
domain = [
|
||||
'|', ('product_id', '=', move.product_id.id),
|
||||
'&', ('product_id', '=', False), ('product_tmpl_id.product_variant_ids', '=', move.product_id.id),
|
||||
('type', '=', 'phantom'),
|
||||
'|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
('company_id', '=', user_company)]
|
||||
return self.pool.get('mrp.bom').search(cr, SUPERUSER_ID, domain, context=context)
|
||||
|
||||
def _action_explode(self, cr, uid, move, context=None):
|
||||
""" Explodes pickings.
|
||||
@param move: Stock moves
|
||||
@return: True
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
bom_obj = self.pool.get('mrp.bom')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
prod_obj = self.pool.get("product.product")
|
||||
proc_obj = self.pool.get("procurement.order")
|
||||
uom_obj = self.pool.get("product.uom")
|
||||
to_explode_again_ids = []
|
||||
processed_ids = []
|
||||
bis = self._check_phantom_bom(cr, uid, move, context=context)
|
||||
if bis:
|
||||
bom_point = bom_obj.browse(cr, SUPERUSER_ID, bis[0], context=context)
|
||||
property_ids = context.get('property_ids') or []
|
||||
bis = bom_obj._bom_find(cr, SUPERUSER_ID, product_id=move.product_id.id, properties=property_ids)
|
||||
bom_point = bom_obj.browse(cr, SUPERUSER_ID, bis, context=context)
|
||||
if bis and bom_point.type == 'phantom':
|
||||
processed_ids = []
|
||||
factor = uom_obj._compute_qty(cr, SUPERUSER_ID, move.product_uom.id, move.product_uom_qty, bom_point.product_uom.id) / bom_point.product_qty
|
||||
res = bom_obj._bom_explode(cr, SUPERUSER_ID, bom_point, move.product_id, factor, [], context=context)
|
||||
res = bom_obj._bom_explode(cr, SUPERUSER_ID, bom_point, move.product_id, factor, property_ids, context=context)
|
||||
|
||||
for line in res[0]:
|
||||
product = prod_obj.browse(cr, uid, line['product_id'], context=context)
|
||||
|
@ -115,7 +103,6 @@ class StockMove(osv.osv):
|
|||
proc = proc_obj.create(cr, uid, valdef, context=context)
|
||||
proc_obj.run(cr, uid, [proc], context=context) #could be omitted
|
||||
|
||||
|
||||
#check if new moves needs to be exploded
|
||||
if to_explode_again_ids:
|
||||
for new_move in self.browse(cr, uid, to_explode_again_ids, context=context):
|
||||
|
@ -133,8 +120,10 @@ class StockMove(osv.osv):
|
|||
|
||||
#delete the move with original product which is not relevant anymore
|
||||
move_obj.unlink(cr, SUPERUSER_ID, [move.id], context=context)
|
||||
#return list of newly created move or the move id otherwise, unless there is no move anymore
|
||||
return processed_ids or (not bis and [move.id]) or []
|
||||
#return list of newly created move
|
||||
return processed_ids
|
||||
|
||||
return [move.id]
|
||||
|
||||
def action_confirm(self, cr, uid, ids, context=None):
|
||||
move_ids = []
|
||||
|
|
|
@ -100,3 +100,13 @@ class stock_move(osv.osv):
|
|||
if res and move.procurement_id and move.procurement_id.property_ids:
|
||||
res['property_ids'] = [(6, 0, [x.id for x in move.procurement_id.property_ids])]
|
||||
return res
|
||||
|
||||
def _action_explode(self, cr, uid, move, context=None):
|
||||
""" Explodes pickings.
|
||||
@param move: Stock moves
|
||||
@return: True
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
property_ids = map(int, move.procurement_id.sale_line_id.property_ids or [])
|
||||
return super(stock_move, self)._action_explode(cr, uid, move, context=dict(context, property_ids=property_ids))
|
||||
|
|
Loading…
Reference in New Issue