[WIP] Extending wizard with consume lines

bzr revid: jco@openerp.com-20140116174800-kap083m5jvacsbh6
This commit is contained in:
Josse Colpaert
2014-01-16 18:48:00 +01:00
parent bec9914b05
commit 338013803d
4 changed files with 166 additions and 5 deletions
+83 -2
View File
@@ -772,7 +772,16 @@ class mrp_production(osv.osv):
"""
return 1
def action_produce(self, cr, uid, production_id, production_qty, production_mode, context=None):
def action_produce(self, cr, uid, production_id, production_qty, production_mode, wiz, 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.
If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
@@ -784,7 +793,80 @@ class mrp_production(osv.osv):
"""
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':
# trigger workflow if not products to consume (eg: services)
self.signal_button_produce(cr, uid, [production_id])
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):
continue
produced_qty += produced_product.product_qty
if production_mode in ['consume','consume_produce']:
consumed_data = {}
# Calculate already consumed qtys
for consumed in production.move_lines2:
if consumed.scrapped:
continue
if not consumed_data.get(consumed.product_id.id, False):
consumed_data[consumed.product_id.id] = 0
consumed_data[consumed.product_id.id] += consumed.product_qty
for consume in wiz.consume_lines:
# Search move for the product
corresponding_move = [x for x in production.move_lines if x.product_id.id == consume.product_id.id]
if corresponding_move:
corresponding_move = corresponding_move[0]
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.id, 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.id, context=context)
if production_mode == 'consume_produce':
# To produce remaining qty of final product
#vals = {'state':'confirmed'}
#final_product_todo = [x.id for x in production.move_created_ids]
#stock_mov_obj.write(cr, uid, final_product_todo, vals)
#stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
produced_products = {}
for produced_product in production.move_created_ids2:
if produced_product.scrapped:
continue
if not produced_products.get(produced_product.product_id.id, False):
produced_products[produced_product.product_id.id] = 0
produced_products[produced_product.product_id.id] += produced_product.product_qty
for produce_product in production.move_created_ids:
produced_qty = produced_products.get(produce_product.product_id.id, 0)
subproduct_factor = self._get_subproduct_factor(cr, uid, production.id, produce_product.id, context=context)
rest_qty = (subproduct_factor * production.product_qty) - produced_qty
if rest_qty < (subproduct_factor * production_qty):
prod_name = produce_product.product_id.name_get()[0][1]
raise osv.except_osv(_('Warning!'), _('You are going to produce total %s quantities of "%s".\nBut you can only produce up to total %s quantities.') % ((subproduct_factor * production_qty), prod_name, rest_qty))
if rest_qty > 0 :
stock_mov_obj.action_consume(cr, uid, [produce_product.id], (subproduct_factor * production_qty), context=context)
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 action_produce2(self, cr, uid, production_id, production_qty, production_mode, 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.
If Production mode is consume & produce, all stock move lines of raw materials will be done/consumed
and stock move lines of final product will be also done/produced.
@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).
@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':
# trigger workflow if not products to consume (eg: services)
self.signal_button_produce(cr, uid, [production_id])
@@ -992,7 +1074,6 @@ class mrp_production(osv.osv):
'product_uos': production_line.product_uos and production_line.product_uos.id or False,
'location_id': source_location_id,
'location_dest_id': destination_location_id,
'move_dest_id': parent_move_id,
'company_id': production.company_id.id,
'procure_method': 'make_to_order',
})
+2
View File
@@ -30,6 +30,8 @@ class StockMove(osv.osv):
_columns = {
'production_id': fields.many2one('mrp.production', 'Production Order for Produced Products', select=True),
'raw_material_production_id': fields.many2one('mrp.production', 'Production Order for Raw Materials', select=True),
'consumed_for': fields.many2one('stock.move', 'Consumed for'),
'track_production': fields.related('product_id', 'track_production'),
}
def check_tracking(self, cr, uid, move, lot_id, context=None):
+62 -1
View File
@@ -22,6 +22,18 @@
from openerp.osv import fields, osv
import openerp.addons.decimal_precision as dp
class mrp_product_produce_line(osv.osv_memory):
_name="mrp.product.produce.line"
_description = "Product Produce Consume lines"
_columns = {
'product_id': fields.many2one('product.product', 'Product'),
'product_qty': fields.float('Quantity'),
'lot_id': fields.many2one('stock.production.lot', 'Lot'),
'produce_id': fields.many2one('mrp.product.produce')
}
class mrp_product_produce(osv.osv_memory):
_name = "mrp.product.produce"
_description = "Product Produce"
@@ -33,7 +45,56 @@ class mrp_product_produce(osv.osv_memory):
help="'Consume only' mode will only consume the products with the quantity selected.\n"
"'Consume & Produce' mode will consume as well as produce the products with the quantity selected "
"and it will finish the production order when total ordered quantities are produced."),
'lot_id': fields.many2one('stock.production.lot', 'Lot'), #Should only be visible when it is consume and produce mode
'consume_lines': fields.one2many('mrp.product.produce.line', 'produce_id', 'Products Consumed'),
}
def on_change_qty(self, cr, uid, ids, product_qty, consume_lines, context=None):
""" Will calculate number of products based on
"""
prod_obj = self.pool.get("mrp.production")
production = prod_obj.browse(cr, uid, context['active_id'], context=context)
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):
continue
produced_qty += produced_product.product_qty
#Calculate consume lines
consumed_data = {}
for consumed in production.move_lines2:
if consumed.scrapped:
continue
if not consumed_data.get(consumed.product_id.id, False):
consumed_data[consumed.product_id.id] = 0
consumed_data[consumed.product_id.id] += consumed.product_qty
print "Consumed data", consumed_data
new_consume_lines = []
# Find product qty to be consumed and consume it
for scheduled in production.product_lines:
# total qty of consumed product we need after this consumption
total_consume = ((product_qty + produced_qty) * scheduled.product_qty / production.product_qty)
# qty available for consume and produce
qty_avail = scheduled.product_qty - consumed_data.get(scheduled.product_id.id, 0.0)
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)
dict_new = {'product_id': scheduled.product_id.id, 'product_qty': qty}
new_consume_lines.append([0, False, dict_new])
return {'value': {'consume_lines': new_consume_lines}}
def _get_product_qty(self, cr, uid, context=None):
""" To obtain product quantity
@@ -64,7 +125,7 @@ class mrp_product_produce(osv.osv_memory):
assert production_id, "Production Id should be specified in context as a Active ID."
data = self.browse(cr, uid, ids[0], context=context)
self.pool.get('mrp.production').action_produce(cr, uid, production_id,
data.product_qty, data.mode, context=context)
data.product_qty, data.mode, data, context=context)
return {}
+19 -2
View File
@@ -12,8 +12,25 @@
<form string="Produce" version="7.0">
<group string="Produce">
<field name="mode"/>
<field name="product_qty" colspan="2"/>
</group>
<field name="product_qty" colspan="2" on_change="on_change_qty(product_qty, consume_lines, context)"/>
<field name="lot_id" domain="[('product_id', '=', product_id)]"
attrs="{'required': [('track_production','=',True)]}"
context="{'default_product_id':product_id}"
groups="stock.group_tracking_lot"/>
</group>
<separator/>
<group string="To Consume">
<field name="consume_lines">
<tree string="Consume Lines" editable="top">
<field name="product_id"/>
<field name="product_qty"/>
<field name="lot_id" domain="[('product_id', '=', product_id)]"
attrs="{'required': [('track_production','=',True)]}"
context="{'default_product_id':product_id}"
groups="stock.group_tracking_lot"/>
</tree>
</field>
</group>
<footer>
<button name="do_produce" type="object" string="Confirm" class="oe_highlight"/>
or