[MERGE] [FIX] mrp: producing a BoM of type service is no longer blocked in ready state, correctly transmit project reference when create task from sale order

bzr revid: mat@openerp.com-20130916113323-8an09x0d7svv2j7d
This commit is contained in:
Martin Trigaux
2013-09-16 13:33:23 +02:00
4 changed files with 209 additions and 24 deletions
+1
View File
@@ -77,6 +77,7 @@ Dashboard / Reports for MRP will include:
#TODO: This yml tests are needed to be completely reviewed again because the product wood panel is removed in product demo as it does not suit for new demo context of computer and consultant company
# so the ymls are too complex to change at this stage
'test': [
'test/bom_with_service_type_product.yml',
# 'test/order_demo.yml',
# 'test/order_process.yml',
# 'test/cancel_order.yml',
+56 -24
View File
@@ -591,12 +591,12 @@ class mrp_production(osv.osv):
"""
self.write(cr, uid, ids, {'state': 'picking_except'})
return True
def action_compute(self, cr, uid, ids, properties=None, context=None):
""" Computes bills of material of a product.
@param properties: List containing dictionaries of properties.
@return: No. of products.
def _action_compute_lines(self, cr, uid, ids, properties=None, context=None):
""" Compute product_lines and workcenter_lines from BoM structure
@return: product_lines
"""
if properties is None:
properties = []
results = []
@@ -604,13 +604,15 @@ class mrp_production(osv.osv):
uom_obj = self.pool.get('product.uom')
prod_line_obj = self.pool.get('mrp.production.product.line')
workcenter_line_obj = self.pool.get('mrp.production.workcenter.line')
for production in self.browse(cr, uid, ids):
p_ids = prod_line_obj.search(cr, SUPERUSER_ID, [('production_id', '=', production.id)], context=context)
prod_line_obj.unlink(cr, SUPERUSER_ID, p_ids, context=context)
w_ids = workcenter_line_obj.search(cr, SUPERUSER_ID, [('production_id', '=', production.id)], context=context)
workcenter_line_obj.unlink(cr, SUPERUSER_ID, w_ids, context=context)
for production in self.browse(cr, uid, ids, context=context):
#unlink product_lines
prod_line_obj.unlink(cr, SUPERUSER_ID, [line.id for line in production.product_lines], context=context)
#unlink workcenter_lines
workcenter_line_obj.unlink(cr, SUPERUSER_ID, [line.id for line in production.workcenter_lines], context=context)
# search BoM structure and route
bom_point = production.bom_id
bom_id = production.bom_id.id
if not bom_point:
@@ -619,20 +621,33 @@ class mrp_production(osv.osv):
bom_point = bom_obj.browse(cr, uid, bom_id)
routing_id = bom_point.routing_id.id or False
self.write(cr, uid, [production.id], {'bom_id': bom_id, 'routing_id': routing_id})
if not bom_id:
raise osv.except_osv(_('Error!'), _("Cannot find a bill of material for this product."))
# get components and workcenter_lines from BoM structure
factor = uom_obj._compute_qty(cr, uid, production.product_uom.id, production.product_qty, bom_point.product_uom.id)
res = bom_obj._bom_explode(cr, uid, bom_point, factor / bom_point.product_qty, properties, routing_id=production.routing_id.id)
results = res[0]
results2 = res[1]
results = res[0] # product_lines
results2 = res[1] # workcenter_lines
# reset product_lines in production order
for line in results:
line['production_id'] = production.id
prod_line_obj.create(cr, uid, line)
#reset workcenter_lines in production order
for line in results2:
line['production_id'] = production.id
workcenter_line_obj.create(cr, uid, line)
return len(results)
return results
def action_compute(self, cr, uid, ids, properties=None, context=None):
""" Computes bills of material of a product.
@param properties: List containing dictionaries of properties.
@return: No. of products.
"""
return len(self._action_compute_lines(cr, uid, ids, properties=properties, context=context))
def action_cancel(self, cr, uid, ids, context=None):
""" Cancels the production order and related stock moves.
@@ -659,8 +674,12 @@ class mrp_production(osv.osv):
move_obj = self.pool.get('stock.move')
self.write(cr, uid, ids, {'state': 'ready'})
for (production_id,name) in self.name_get(cr, uid, ids):
production = self.browse(cr, uid, production_id)
for production in self.browse(cr, uid, ids, context=context):
if not production.move_created_ids:
produce_move_id = self._make_production_produce_line(cr, uid, production, context=context)
for scheduled in production.product_lines:
self._make_production_line_procurement(cr, uid, scheduled, False, context=context)
if production.move_prod_id and production.move_prod_id.location_id.id != production.location_dest_id.id:
move_obj.write(cr, uid, [production.move_prod_id.id],
{'location_id': production.location_dest_id.id})
@@ -712,6 +731,11 @@ class mrp_production(osv.osv):
stock_mov_obj = self.pool.get('stock.move')
production = self.browse(cr, uid, production_id, context=context)
wf_service = netsvc.LocalService("workflow")
if not production.move_lines and production.state == 'ready':
# trigger workflow if not products to consume (eg: services)
wf_service.trg_validate(uid, 'mrp.production', production_id, 'button_produce', cr)
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):
@@ -789,7 +813,6 @@ class mrp_production(osv.osv):
for new_parent_id in new_parent_ids:
stock_mov_obj.write(cr, uid, [raw_product.id], {'move_history_ids': [(4,new_parent_id)]})
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'mrp.production', production_id, 'button_produce_done', cr)
return True
@@ -849,13 +872,19 @@ class mrp_production(osv.osv):
"""
res = True
for production in self.browse(cr, uid, ids):
if not production.product_lines:
if not self.action_compute(cr, uid, [production.id]):
res = False
boms = self._action_compute_lines(cr, uid, [production.id])
res = False
for bom in boms:
product = self.pool.get('product.product').browse(cr, uid, bom['product_id'])
if product.type in ('product', 'consu'):
res = True
return res
def _get_auto_picking(self, cr, uid, production):
return True
def _hook_create_post_procurement(self, cr, uid, production, procurement_id, context=None):
return True
def _make_production_line_procurement(self, cr, uid, production_line, shipment_move_id, context=None):
wf_service = netsvc.LocalService("workflow")
@@ -878,6 +907,7 @@ class mrp_production(osv.osv):
'move_id': shipment_move_id,
'company_id': production.company_id.id,
})
self._hook_create_post_procurement(cr, uid, production, procurement_id, context=context)
wf_service.trg_validate(uid, procurement_order._name, procurement_id, 'button_confirm', cr)
return procurement_id
@@ -1005,11 +1035,13 @@ class mrp_production(osv.osv):
for line in production.product_lines:
consume_move_id = self._make_production_consume_line(cr, uid, line, produce_move_id, source_location_id=source_location_id, context=context)
shipment_move_id = self._make_production_internal_shipment_line(cr, uid, line, shipment_id, consume_move_id,\
if shipment_id:
shipment_move_id = self._make_production_internal_shipment_line(cr, uid, line, shipment_id, consume_move_id,\
destination_location_id=source_location_id, context=context)
self._make_production_line_procurement(cr, uid, line, shipment_move_id, context=context)
self._make_production_line_procurement(cr, uid, line, shipment_move_id, context=context)
wf_service.trg_validate(uid, 'stock.picking', shipment_id, 'button_confirm', cr)
if shipment_id:
wf_service.trg_validate(uid, 'stock.picking', shipment_id, 'button_confirm', cr)
production.write({'state':'confirmed'}, context=context)
return shipment_id
@@ -0,0 +1,134 @@
-
I create Bill of Materials with one service type product and one consumable product.
-
!record {model: mrp.bom, id: mrp_bom_test1}:
company_id: base.main_company
name: PC Assemble SC234
product_id: product.product_product_3
product_qty: 1.0
type: normal
bom_lines:
- company_id: base.main_company
name: On Site Assistance
product_id: product.product_product_2
product_qty: 1.0
- company_id: base.main_company
name: GrapWorks Software
product_id: product.product_product_44
product_qty: 1.0
-
I make the production order using BoM having one service type product and one consumable product.
-
!record {model: mrp.production, id: mrp_production_servicetype_mo1}:
product_id: product.product_product_5
product_qty: 1.0
bom_id: mrp_bom_test1
date_planned: !eval time.strftime('%Y-%m-%d %H:%M:%S')
-
I compute the data of production order.
-
!python {model: mrp.production}: |
self.action_compute(cr, uid, [ref("mrp_production_servicetype_mo1")], {"lang": "en_US", "tz": False, "search_default_Current": 1,
"active_model": "ir.ui.menu", "active_ids": [ref("mrp.menu_mrp_production_action")],
"active_id": ref("mrp.menu_mrp_production_action"), })
-
I confirm the production order.
-
!workflow {model: mrp.production, action: button_confirm, ref: mrp_production_servicetype_mo1}
-
I confirm the Consume Products.
-
!python {model: mrp.production}: |
order = self.browse(cr, uid, ref("mrp_production_servicetype_mo1"))
assert order.state == 'confirmed', "Production order should be confirmed."
for move_line in order.move_lines:
move_line.action_consume(move_line.product_qty)
-
I processed the Product Entirely.
-
!python {model: mrp.production}: |
order = self.browse(cr, uid, ref("mrp_production_servicetype_mo1"))
assert order.state == 'in_production', 'Production order should be in production State.'
for move_created in order.move_created_ids:
move_created.action_done()
-
I produce product.
-
!python {model: mrp.product.produce}: |
context.update({'active_id': ref('mrp_production_servicetype_mo1')})
-
!record {model: mrp.product.produce, id: mrp_product_produce_1}:
mode: 'consume_produce'
-
!python {model: mrp.product.produce}: |
self.do_produce(cr, uid, [ref('mrp_product_produce_1')], context=context)
-
I check production order after produced.
-
!python {model: mrp.production}: |
order = self.browse(cr, uid, ref("mrp_production_servicetype_mo1"))
assert order.state == 'done', "Production order should be closed."
-
I create Bill of Materials with two service type products.
-
!record {model: mrp.bom, id: mrp_bom_test_2}:
company_id: base.main_company
name: PC Assemble SC234
product_id: product.product_product_3
product_qty: 1.0
type: normal
bom_lines:
- company_id: base.main_company
name: On Site Monitoring
product_id: product.product_product_1
product_qty: 1.0
- company_id: base.main_company
name: On Site Assistance
product_id: product.product_product_2
product_qty: 1.0
-
I make the production order using BoM having two service type products.
-
!record {model: mrp.production, id: mrp_production_servicetype_2}:
product_id: product.product_product_5
product_qty: 1.0
bom_id: mrp_bom_test_2
date_planned: !eval time.strftime('%Y-%m-%d %H:%M:%S')
-
I compute the data of production order.
-
!python {model: mrp.production}: |
self.action_compute(cr, uid, [ref("mrp_production_servicetype_2")], {"lang": "en_US", "tz": False, "search_default_Current": 1,
"active_model": "ir.ui.menu", "active_ids": [ref("mrp.menu_mrp_production_action")],
"active_id": ref("mrp.menu_mrp_production_action"), })
-
I confirm the production order.
-
!workflow {model: mrp.production, action: button_confirm, ref: mrp_production_servicetype_2}
-
Now I start production.
-
!workflow {model: mrp.production, action: button_produce, ref: mrp_production_servicetype_2}
-
I check that production order in production state after start production.
-
!python {model: mrp.production}: |
order = self.browse(cr, uid, ref("mrp_production_servicetype_2"))
assert order.state == 'in_production', 'Production order should be in production State.'
-
I produce product.
-
!python {model: mrp.product.produce}: |
context.update({'active_id': ref('mrp_production_servicetype_2')})
-
!record {model: mrp.product.produce, id: mrp_product_produce_2}:
mode: 'consume_produce'
-
!python {model: mrp.product.produce}: |
self.do_produce(cr, uid, [ref('mrp_product_produce_2')], context=context)
-
I check production order after produced.
-
!python {model: mrp.production}: |
order = self.browse(cr, uid, ref("mrp_production_servicetype_2"))
assert order.state == 'done', "Production order should be closed."
+18
View File
@@ -109,4 +109,22 @@ class sale_order(osv.osv):
}
sale_order()
class mrp_production(osv.osv):
_inherit = 'mrp.production'
def _hook_create_post_procurement(self, cr, uid, production, procurement_id, context=None):
def get_parent_move(move):
if move.move_dest_id:
return get_parent_move(move.move_dest_id)
return move
res = super(mrp_production, self)._hook_create_post_procurement(cr, uid, production, procurement_id, context)
if production.move_prod_id:
parent_move_line = get_parent_move(production.move_prod_id)
if parent_move_line and parent_move_line.sale_line_id:
self.pool.get('procurement.order').write(cr, uid, procurement_id, {'sale_line_id': parent_move_line.sale_line_id.id})
return res
mrp_production()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: