[REF] mrp, stock: refactoring made during code review

bzr revid: qdp-launchpad@openerp.com-20140205104324-5h5hu0fv71omhigf
This commit is contained in:
Quentin (OpenERP) 2014-02-05 11:43:24 +01:00
parent 2c101e9432
commit 0afb7076d4
4 changed files with 61 additions and 65 deletions

View File

@ -772,6 +772,8 @@ class mrp_production(osv.osv):
return 1
def _get_produced_qty(self, cr, uid, production, context=None):
''' returns the produced quantity of product 'production.product_id' for the given production, in the product UoM
'''
produced_qty = 0
for produced_product in production.move_created_ids2:
if (produced_product.scrapped) or (produced_product.product_id.id != production.product_id.id):
@ -780,6 +782,8 @@ class mrp_production(osv.osv):
return produced_qty
def _get_consumed_data(self, cr, uid, production, context=None):
''' returns a dictionary containing for each raw material of the given production, its quantity already consumed (in the raw material UoM)
'''
consumed_data = {}
# Calculate already consumed qtys
for consumed in production.move_lines2:
@ -790,71 +794,68 @@ class mrp_production(osv.osv):
consumed_data[consumed.product_id.id] += consumed.product_qty
return consumed_data
def _calculate_qty(self, cr, uid, production, product_qty = 0.0, context=None):
def _calculate_qty(self, cr, uid, production, product_qty=0.0, context=None):
"""
Calculates the quantity still needed to produce an extra number of products
"""
quant_obj = self.pool.get("stock.quant")
#In case no product qty is given, take product qty of
if product_qty == 0.0:
done = 0.0
for move in production.move_created_ids2:
if move.product_id == production.product_id:
if not move.scrapped:
done += move.product_qty
product_qty = production.product_qty - done
produced_qty = self._get_produced_qty(cr, uid, production, context=context)
consumed_data = self._get_consumed_data(cr, uid, production, context=context)
#In case no product_qty is given, take the remaining qty to produce for the given production
if not product_qty:
product_qty = production.product_qty - produced_qty
dicts = {}
# Find product qty to be consumed and consume it
for scheduled in production.product_lines:
if not dicts.get(scheduled.product_id.id):
dicts[scheduled.product_id.id] = {}
# total qty of consumed product we need after this consumption
total_consume = ((product_qty + produced_qty) * scheduled.product_qty / production.product_qty)
consumed_qty = consumed_data.get(scheduled.product_id.id, 0.0)
# qty available for consume and produce
qty_avail = scheduled.product_qty - consumed_data.get(scheduled.product_id.id, 0.0)
qty_avail = scheduled.product_qty - consumed_qty
if qty_avail <= 0.0:
# there will be nothing to consume for this raw material
continue
qty = total_consume - consumed_data.get(scheduled.product_id.id, 0.0)
if not dicts.get(scheduled.product_id.id):
dicts[scheduled.product_id.id] = {}
# total qty of consumed product we need after this consumption
total_consume = ((product_qty + produced_qty) * scheduled.product_qty / production.product_qty)
qty = total_consume - consumed_qty
# Search for quants related to this related move
move = [x for x in production.move_lines if x.product_id.id == scheduled.product_id.id]
#TODO: check if not already in dict_new
if move:
for move in production.move_lines:
if qty <= 0.0:
break
if move.product_id.id != scheduled.product_id.id:
continue
product_id = scheduled.product_id.id
move = move[0]
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, scheduled.product_id, qty, domain=[('qty', '>', 0.0)],
q = min(move.product_qty, qty)
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, scheduled.product_id, q, domain=[('qty', '>', 0.0)],
prefered_domain=[('reservation_id', '=', move.id)], fallback_domain=[('reservation_id', '=', False)], context=context)
for quant in quants:
if quant[0]:
lot_id = quant[0].lot_id.id
prod_qty = quant[1]
for quant, quant_qty in quants:
if quant:
lot_id = quant.lot_id.id
if not product_id in dicts.keys():
dicts[product_id] = {lot_id : prod_qty}
dicts[product_id] = {lot_id : quant_qty}
elif lot_id in dicts[product_id].keys():
dicts[product_id][lot_id] += prod_qty
dicts[product_id][lot_id] += quant_qty
else:
dicts[product_id][lot_id] = prod_qty
qty -= quant[1]
if qty > 0:
if dicts[product_id].get(False):
dicts[product_id][False] += qty
else:
dicts[product_id][False] = qty
dicts[product_id][lot_id] = quant_qty
qty -= quant_qty
if qty > 0:
if dicts[product_id].get(False):
dicts[product_id][False] += qty
else:
dicts[product_id][False] = qty
consume_lines = []
for prod in dicts.keys():
for lot in dicts[prod].keys():
consume_lines.append({'product_id': prod, 'product_qty':dicts[prod][lot], 'lot_id': lot})
for lot, qty in dicts[prod].items():
consume_lines.append({'product_id': prod, 'product_qty': qty, 'lot_id': lot})
return consume_lines
def action_produce(self, cr, uid, production_id, production_qty, production_mode, wiz=False, context=None):
""" To produce final product based on production mode (consume/consume&produce).
If Production mode is consume, all stock move lines of raw materials will be done/consumed.
@ -863,11 +864,9 @@ class mrp_production(osv.osv):
@param production_id: the ID of mrp.production object
@param production_qty: specify qty to produce
@param production_mode: specify production mode (consume/consume&produce).
@param wizard: the mrp produce product wizard, which will tell the amount of consumed products needed
@param wiz: the mrp produce product wizard, which will tell the amount of consumed products needed
@return: True
"""
stock_mov_obj = self.pool.get('stock.move')
production = self.browse(cr, uid, production_id, context=context)
if not production.move_lines and production.state == 'ready':
@ -902,36 +901,33 @@ class mrp_production(osv.osv):
lot_id = False
if wiz:
lot_id = wiz.lot_id.id
new_moves = stock_mov_obj.action_consume(cr, uid, [produce_product.id], (subproduct_factor * production_qty), location_id = produce_product.location_id.id, restrict_lot_id = lot_id, context=context)
new_moves = stock_mov_obj.action_consume(cr, uid, [produce_product.id], (subproduct_factor * production_qty), location_id=produce_product.location_id.id, restrict_lot_id=lot_id, context=context)
if produce_product.product_id.id == production.product_id.id and new_moves:
main_production_move = new_moves[0]
if production_mode in ['consume','consume_produce']:
consume_lines = []
if wiz:
consume_lines = []
for cons in wiz.consume_lines:
consume_lines.append({'product_id': cons.product_id.id, 'lot_id': cons.lot_id.id, 'product_qty': cons.product_qty})
else:
consume_lines = self._calculate_qty(cr, uid, production, production_qty, context=context)
for consume in consume_lines:
# Search move for the product
corresponding_move = [x for x in production.move_lines if x.product_id.id == consume['product_id']]
if corresponding_move:
corresponding_move = corresponding_move[0]
default_values = {}
if corresponding_move.product_qty > consume['product_qty']:
stock_mov_obj.action_consume(cr, uid, [corresponding_move.id], consume['product_qty'], corresponding_move.location_id.id,
restrict_lot_id = consume['lot_id'], consumed_for = main_production_move, context=context)
else:
stock_mov_obj.action_consume(cr, uid, [corresponding_move.id], corresponding_move.product_qty, corresponding_move.location_id.id,
restrict_lot_id = consume['lot_id'], consumed_for = main_production_move, context=context)
remaining_qty = consume['product_qty']
for raw_material_line in production.move_lines:
if remaining_qty <= 0:
break
if consume[product_id] != raw_material.product_id.id:
continue
consumed_qty = min(remaining_qty, raw_material_line.product_qty)
stock_mov_obj.action_consume(cr, uid, [corresponding_move.id], consumed_qty, corresponding_move.location_id.id,
restrict_lot_id=consume['lot_id'], consumed_for=main_production_move, context=context)
remaining_qty -= consumed_qty
self.message_post(cr, uid, production_id, body=_("%s produced") % self._description, context=context)
self.signal_button_produce_done(cr, uid, [production_id])
return True
def _costs_generate(self, cr, uid, production):
""" Calculates total costs at the end of the production.
@param production: Id of production order.

View File

@ -113,6 +113,8 @@ class StockMove(osv.osv):
@param consumed_for: optionnal parameter given to this function to make the link between raw material consumed and produced product, for a better traceability
@return: Consumed lines
"""
if context is None:
context = {}
res = []
production_obj = self.pool.get('mrp.production')
uom_obj = self.pool.get('product.uom')

View File

@ -20,7 +20,6 @@
attrs="{'required': [('track_production', '=', True), ('mode', '=', 'consume_produce')]}"
groups="stock.group_tracking_lot"/>
</group>
<separator/>
<group string="To Consume">
<field name="consume_lines">
<tree string="Consume Lines" editable="top">

View File

@ -285,17 +285,17 @@ class stock_quant(osv.osv):
def quants_reserve(self, cr, uid, quants, move, link=False, context=None):
'''This function reserves quants for the given move (and optionally given link). If the total of quantity reserved is enough, the move's state
is also set to 'assigned' Please do not pass negative quants.
is also set to 'assigned'
:param quants: list of tuple(quant browse record or None, qty to reserve). If None is given as first tuple element, the item will be ignored
:param quants: list of tuple(quant browse record or None, qty to reserve). If None is given as first tuple element, the item will be ignored. Negative quants should not be received as argument
:param move: browse record
:param link: browse record (stock.move.operation.link)
'''
toreserve = []
#split quants if needed
for quant, qty in quants:
if qty < 0.0:
raise osv.except_osv(_('Error!'), _('You can not reserve negative quants. '))
if qty <= 0.0 or quant.qty <= 0.0:
raise osv.except_osv(_('Error!'), _('You can not reserve a negative quantity or a negative quant.'))
if not quant:
continue
self._quant_split(cr, uid, quant, qty, context=context)
@ -1997,7 +1997,6 @@ class stock_move(osv.osv):
return new_move
class stock_inventory(osv.osv):
_name = "stock.inventory"
_description = "Inventory"