[IMP] Update module descriptions of procurement and product_extended + _bom_find and properties

Module description of procurement was deprecated (talking about mrp, ...) and in product_extended
it described things not implemented in the module.

In _bom_find, we passed a UoM which was not used in Saas-4 and it would not be logical that you
need to select a BoM that matches the UoM, so I removed it.

In the demo data, there was still a push rule which triggered a move from output to pack.  The copy=False
is correct for production_id when you would have these push rules.

For the properties: we want to allow to take a bom which has no properties, but only when there is no other
BoM matching the properties we pass.

Update module descriptions

[IMP] production_id copy + no round

[IMP] _bom_find without uom, property correction
This commit is contained in:
Josse Colpaert 2014-09-26 10:40:55 +02:00
parent 3dcb020373
commit 25d2ed6d4b
11 changed files with 37 additions and 39 deletions

View File

@ -230,7 +230,7 @@ class mrp_bom(osv.osv):
} }
_order = "sequence" _order = "sequence"
def _bom_find(self, cr, uid, product_uom, product_tmpl_id=None, product_id=None, properties=None, context=None): def _bom_find(self, cr, uid, product_tmpl_id=None, product_id=None, properties=None, context=None):
""" Finds BoM for particular product and product uom. """ Finds BoM for particular product and product uom.
@param product_tmpl_id: Selected product. @param product_tmpl_id: Selected product.
@param product_uom: Unit of measure of a product. @param product_uom: Unit of measure of a product.
@ -254,16 +254,18 @@ class mrp_bom(osv.osv):
else: else:
# neither product nor template, makes no sense to search # neither product nor template, makes no sense to search
return False return False
if product_uom:
domain += [('product_uom','=',product_uom)]
domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)), domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))] '|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
# order to prioritize bom with product_id over the one without # order to prioritize bom with product_id over the one without
ids = self.search(cr, uid, domain, order='product_id') ids = self.search(cr, uid, domain, order='product_id')
bom_empty_prop = False
for bom in self.pool.get('mrp.bom').browse(cr, uid, ids): for bom in self.pool.get('mrp.bom').browse(cr, uid, ids):
if not set(map(int, bom.property_ids or [])) - set(properties or []): if not set(map(int, bom.property_ids or [])) - set(properties or []):
return bom.id if not bom.property_ids:
return False bom_empty_prop = bom.id
else:
return 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): def _bom_explode(self, cr, uid, bom, product, factor, properties=None, level=0, routing_id=False, previous_products=None, master_bom=None, context=None):
""" Finds Products and Work Centers for related BoM for manufacturing order. """ Finds Products and Work Centers for related BoM for manufacturing order.
@ -322,7 +324,7 @@ class mrp_bom(osv.osv):
raise osv.except_osv(_('Invalid Action!'), _('BoM "%s" contains a BoM line with a product recursion: "%s".') % (master_bom.name,bom_line_id.product_id.name_get()[0][1])) raise osv.except_osv(_('Invalid Action!'), _('BoM "%s" contains a BoM line with a product recursion: "%s".') % (master_bom.name,bom_line_id.product_id.name_get()[0][1]))
quantity = _factor(bom_line_id.product_qty * factor, bom_line_id.product_efficiency, bom_line_id.product_rounding) quantity = _factor(bom_line_id.product_qty * factor, bom_line_id.product_efficiency, bom_line_id.product_rounding)
bom_id = self._bom_find(cr, uid, bom_line_id.product_uom.id, product_id=bom_line_id.product_id.id, properties=properties, context=context) bom_id = self._bom_find(cr, uid, product_id=bom_line_id.product_id.id, properties=properties, context=context)
#If BoM should not behave like PhantoM, just add the product, otherwise explode further #If BoM should not behave like PhantoM, just add the product, otherwise explode further
if bom_line_id.type != "phantom" and (not bom_id or self.browse(cr, uid, bom_id, context=context).type != "phantom"): if bom_line_id.type != "phantom" and (not bom_id or self.browse(cr, uid, bom_id, context=context).type != "phantom"):
@ -403,7 +405,7 @@ class mrp_bom_line(osv.osv):
'routing_id': fields.many2one('mrp.routing', 'Routing', help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production planning."), 'routing_id': fields.many2one('mrp.routing', 'Routing', help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production planning."),
'product_rounding': fields.float('Product Rounding', help="Rounding applied on the product quantity."), 'product_rounding': fields.float('Product Rounding', help="Rounding applied on the product quantity."),
'product_efficiency': fields.float('Manufacturing Efficiency', required=True, help="A factor of 0.9 means a loss of 10% within the production process."), 'product_efficiency': fields.float('Manufacturing Efficiency', required=True, help="A factor of 0.9 means a loss of 10% within the production process."),
'property_ids': fields.many2many('mrp.property', string='Properties'), 'property_ids': fields.many2many('mrp.property', string='Properties'), #Not used
'bom_id': fields.many2one('mrp.bom', 'Parent BoM', ondelete='cascade', select=True, required=True), 'bom_id': fields.many2one('mrp.bom', 'Parent BoM', ondelete='cascade', select=True, required=True),
'attribute_value_ids': fields.many2many('product.attribute.value', string='Variants', help="BOM Product Variants needed form apply this line."), 'attribute_value_ids': fields.many2many('product.attribute.value', string='Variants', help="BOM Product Variants needed form apply this line."),
@ -645,7 +647,7 @@ class mrp_production(osv.osv):
}} }}
bom_obj = self.pool.get('mrp.bom') bom_obj = self.pool.get('mrp.bom')
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
bom_id = bom_obj._bom_find(cr, uid, product.uom_id and product.uom_id.id, product_id=product.id, properties=[], context=context) bom_id = bom_obj._bom_find(cr, uid, product_id=product.id, properties=[], context=context)
routing_id = False routing_id = False
if bom_id: if bom_id:
bom_point = bom_obj.browse(cr, uid, bom_id, context=context) bom_point = bom_obj.browse(cr, uid, bom_id, context=context)
@ -694,7 +696,7 @@ class mrp_production(osv.osv):
bom_point = production.bom_id bom_point = production.bom_id
bom_id = production.bom_id.id bom_id = production.bom_id.id
if not bom_point: if not bom_point:
bom_id = bom_obj._bom_find(cr, uid, production.product_uom.id, product_id=production.product_id.id, properties=properties, context=context) bom_id = bom_obj._bom_find(cr, uid, product_id=production.product_id.id, properties=properties, context=context)
if bom_id: if bom_id:
bom_point = bom_obj.browse(cr, uid, bom_id) bom_point = bom_obj.browse(cr, uid, bom_id)
routing_id = bom_point.routing_id.id or False routing_id = bom_point.routing_id.id or False

View File

@ -62,8 +62,8 @@ class procurement_order(osv.osv):
""" """
for procurement in self.browse(cr, uid, ids, context=context): for procurement in self.browse(cr, uid, ids, context=context):
properties = [x.id for x in procurement.property_ids] properties = [x.id for x in procurement.property_ids]
bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, procurement.product_uom.id, bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, product_id=procurement.product_id.id,
product_id=procurement.product_id.id, properties=properties, context=context) properties=properties, context=context)
if not bom_id: if not bom_id:
return False return False
return True return True
@ -84,8 +84,8 @@ class procurement_order(osv.osv):
routing_id = procurement.bom_id.routing_id.id routing_id = procurement.bom_id.routing_id.id
else: else:
properties = [x.id for x in procurement.property_ids] properties = [x.id for x in procurement.property_ids]
bom_id = bom_obj._bom_find(cr, uid, procurement.product_uom.id, bom_id = bom_obj._bom_find(cr, uid, product_id=procurement.product_id.id,
product_id=procurement.product_id.id, properties=properties, context=context) properties=properties, context=context)
bom = bom_obj.browse(cr, uid, bom_id, context=context) bom = bom_obj.browse(cr, uid, bom_id, context=context)
routing_id = bom.routing_id.id routing_id = bom.routing_id.id

View File

@ -144,7 +144,7 @@ class report_custom(report_rml):
for product in product_pool.browse(cr, uid, ids, context=context): for product in product_pool.browse(cr, uid, ids, context=context):
product_uom_name = to_xml(product.uom_id.name) product_uom_name = to_xml(product.uom_id.name)
bom_id = bom_pool._bom_find(cr, uid, product.uom_id.id, product_id=product.id, context=context) bom_id = bom_pool._bom_find(cr, uid, product_id=product.id, context=context)
title = "<title>%s</title>" %(_("Cost Structure")) title = "<title>%s</title>" %(_("Cost Structure"))
title += "<title>%s</title>" % (to_xml(product.name)) title += "<title>%s</title>" % (to_xml(product.name))
xml += "<lines style='header'>" + title + prod_header + "</lines>" xml += "<lines style='header'>" + title + prod_header + "</lines>"

View File

@ -78,7 +78,7 @@ class change_production_qty(osv.osv_memory):
bom_point = prod.bom_id bom_point = prod.bom_id
bom_id = prod.bom_id.id bom_id = prod.bom_id.id
if not bom_point: if not bom_point:
bom_id = bom_obj._bom_find(cr, uid, prod.product_uom.id, product_id=prod.product_id.id, context=context) bom_id = bom_obj._bom_find(cr, uid, product_id=prod.product_id.id, context=context)
if not bom_id: if not bom_id:
raise osv.except_osv(_('Error!'), _("Cannot find bill of material for this product.")) raise osv.except_osv(_('Error!'), _("Cannot find bill of material for this product."))
prod_obj.write(cr, uid, [prod.id], {'bom_id': bom_id}) prod_obj.write(cr, uid, [prod.id], {'bom_id': bom_id})

View File

@ -62,7 +62,7 @@ class stock_move_consume(osv.osv_memory):
for data in self.browse(cr, uid, ids, context=context): for data in self.browse(cr, uid, ids, context=context):
if move_ids and move_ids[0]: if move_ids and move_ids[0]:
move = move_obj.browse(cr, uid, move_ids[0], context=context) move = move_obj.browse(cr, uid, move_ids[0], context=context)
qty = uom_obj._compute_qty(cr, uid, data['product_uom'].id, data.product_qty, data.product_id.uom_id.id, round=False) qty = uom_obj._compute_qty(cr, uid, data['product_uom'].id, data.product_qty, data.product_id.uom_id.id)
move_obj.action_consume(cr, uid, move_ids, move_obj.action_consume(cr, uid, move_ids,
qty, data.location_id.id, restrict_lot_id=data.restrict_lot_id.id, qty, data.location_id.id, restrict_lot_id=data.restrict_lot_id.id,
context=context) context=context)

View File

@ -123,7 +123,6 @@ class mrp_production_workcenter_line(osv.osv):
else: else:
open_count = self.search_count(cr,uid,[('production_id','=',prod_obj.id), ('state', '!=', 'done')]) open_count = self.search_count(cr,uid,[('production_id','=',prod_obj.id), ('state', '!=', 'done')])
flag = not bool(open_count) flag = not bool(open_count)
if flag: if flag:
for production in prod_obj_pool.browse(cr, uid, [prod_obj.id], context= None): for production in prod_obj_pool.browse(cr, uid, [prod_obj.id], context= None):
if production.move_lines or production.move_created_ids: if production.move_lines or production.move_created_ids:

View File

@ -79,7 +79,7 @@
order = self.browse(cr, uid, ref("mrp.mrp_production_1"), context=context) order = self.browse(cr, uid, ref("mrp.mrp_production_1"), context=context)
order.workcenter_lines[0].signal_workflow('button_cancel') order.workcenter_lines[0].signal_workflow('button_cancel')
- -
I reset first work operation and start after resolving techninal fault of work center. I reset first work operation and start after resolving technical fault of work center.
- -
!python {model: mrp.production}: | !python {model: mrp.production}: |
order = self.browse(cr, uid, ref("mrp.mrp_production_1"), context=context) order = self.browse(cr, uid, ref("mrp.mrp_production_1"), context=context)

View File

@ -31,17 +31,22 @@
This is the module for computing Procurements. This is the module for computing Procurements.
============================================== ==============================================
In the MRP process, procurements orders are created to launch manufacturing This procurement module only depends on the product module and is not useful
orders, purchase orders, stock allocations. Procurement orders are on itself. Procurements represent needs that need to be solved by a procurement
generated automatically by the system and unless there is a problem, the rule. When a procurement is created, it is confirmed. When a rule is found,
user will not be notified. In case of problems, the system will raise some it will be put in running state. After, it will check if what needed to be done
procurement exceptions to inform the user about blocking problems that need for the rule has been executed. Then it will go to the done state. A procurement
to be resolved manually (like, missing BoM structure or missing supplier). can also go into exception, for example when it can not find a rule and it can be cancelled.
The procurement order will schedule a proposal for automatic procurement The mechanism will be extended by several modules. The procurement rule of stock will
for the product which needs replenishment. This procurement will start a create a move and the procurement will be fulfilled when the move is done.
task, either a purchase order form for the supplier, or a production order The procurement rule of sale_service will create a task. Those of purchase or
depending on the product's configuration. mrp will create a purchase order or a manufacturing order.
The scheduler will check if it can assign a rule to confirmed procurements and if
it can put running procurements to done.
Procurements in exception should be checked manually and can be re-run.
""", """,
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',

View File

@ -27,10 +27,8 @@
"category" : "Generic Modules/Inventory Control", "category" : "Generic Modules/Inventory Control",
"description": """ "description": """
Product extension. This module adds: Product extension. This module adds:
* Last purchase order for each product supplier * Computes standard price from the BoM of the product with a button on the product variant based
* New functional field: Available stock (real+outgoing stock) on the materials in the BoM and the work centers. It can create the necessary accounting entries when necessary.
* Computes standard price from the BoM of the product (optional for each product)
* Standard price is shown in the BoM and it can be computed with a wizard
""", """,
"init_xml" : [], "init_xml" : [],
"demo_xml" : [], "demo_xml" : [],

View File

@ -36,7 +36,7 @@ class product_product(osv.osv):
testdict = {} testdict = {}
for prod_id in ids: for prod_id in ids:
bom_obj = self.pool.get('mrp.bom') bom_obj = self.pool.get('mrp.bom')
bom_id = bom_obj._bom_find(cr, uid, False, product_id = prod_id, context=context) bom_id = bom_obj._bom_find(cr, uid, product_id = prod_id, context=context)
if bom_id: if bom_id:
# In recursive mode, it will first compute the prices of child boms # In recursive mode, it will first compute the prices of child boms
if recursive: if recursive:

View File

@ -18,9 +18,3 @@
name: Gate B name: Gate B
usage: internal usage: internal
location_id: location_dispatch_zone location_id: location_dispatch_zone
-
!record {model: stock.location.path, id: push_pick}:
name: Pick List
location_from_id: stock.stock_location_output
location_dest_id: location_pack_zone
picking_type_id: stock.picking_type_internal