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
}
_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.
@param product_tmpl_id: Selected product.
@param product_uom: Unit of measure of a product.
else:
# neither product nor template, makes no sense to search
return False
- if product_uom:
- domain += [('product_uom','=',product_uom)]
domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', 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
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):
if not set(map(int, bom.property_ids or [])) - set(properties or []):
- return bom.id
- return False
+ if not bom.property_ids:
+ 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):
""" Finds Products and Work Centers for related BoM for manufacturing order.
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)
- 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_line_id.type != "phantom" and (not bom_id or self.browse(cr, uid, bom_id, context=context).type != "phantom"):
'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_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),
'attribute_value_ids': fields.many2many('product.attribute.value', string='Variants', help="BOM Product Variants needed form apply this line."),
}}
bom_obj = self.pool.get('mrp.bom')
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
if bom_id:
bom_point = bom_obj.browse(cr, uid, bom_id, context=context)
bom_point = production.bom_id
bom_id = production.bom_id.id
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:
bom_point = bom_obj.browse(cr, uid, bom_id)
routing_id = bom_point.routing_id.id or False
"""
for procurement in self.browse(cr, uid, ids, context=context):
properties = [x.id for x in procurement.property_ids]
- bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, procurement.product_uom.id,
- product_id=procurement.product_id.id, properties=properties, context=context)
+ bom_id = self.pool.get('mrp.bom')._bom_find(cr, uid, product_id=procurement.product_id.id,
+ properties=properties, context=context)
if not bom_id:
return False
return True
routing_id = procurement.bom_id.routing_id.id
else:
properties = [x.id for x in procurement.property_ids]
- bom_id = bom_obj._bom_find(cr, uid, procurement.product_uom.id,
- product_id=procurement.product_id.id, properties=properties, context=context)
+ bom_id = bom_obj._bom_find(cr, uid, product_id=procurement.product_id.id,
+ properties=properties, context=context)
bom = bom_obj.browse(cr, uid, bom_id, context=context)
routing_id = bom.routing_id.id
for product in product_pool.browse(cr, uid, ids, context=context):
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>" % (to_xml(product.name))
xml += "<lines style='header'>" + title + prod_header + "</lines>"
bom_point = prod.bom_id
bom_id = prod.bom_id.id
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:
raise osv.except_osv(_('Error!'), _("Cannot find bill of material for this product."))
prod_obj.write(cr, uid, [prod.id], {'bom_id': bom_id})
for data in self.browse(cr, uid, ids, context=context):
if move_ids and move_ids[0]:
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,
qty, data.location_id.id, restrict_lot_id=data.restrict_lot_id.id,
context=context)
else:
open_count = self.search_count(cr,uid,[('production_id','=',prod_obj.id), ('state', '!=', 'done')])
flag = not bool(open_count)
-
if flag:
for production in prod_obj_pool.browse(cr, uid, [prod_obj.id], context= None):
if production.move_lines or production.move_created_ids:
order = self.browse(cr, uid, ref("mrp.mrp_production_1"), context=context)
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}: |
order = self.browse(cr, uid, ref("mrp.mrp_production_1"), context=context)
This is the module for computing Procurements.
==============================================
-In the MRP process, procurements orders are created to launch manufacturing
-orders, purchase orders, stock allocations. Procurement orders are
-generated automatically by the system and unless there is a problem, the
-user will not be notified. In case of problems, the system will raise some
-procurement exceptions to inform the user about blocking problems that need
-to be resolved manually (like, missing BoM structure or missing supplier).
+This procurement module only depends on the product module and is not useful
+on itself. Procurements represent needs that need to be solved by a procurement
+rule. When a procurement is created, it is confirmed. When a rule is found,
+it will be put in running state. After, it will check if what needed to be done
+for the rule has been executed. Then it will go to the done state. A procurement
+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
-for the product which needs replenishment. This procurement will start a
-task, either a purchase order form for the supplier, or a production order
-depending on the product's configuration.
+The mechanism will be extended by several modules. The procurement rule of stock will
+create a move and the procurement will be fulfilled when the move is done.
+The procurement rule of sale_service will create a task. Those of purchase or
+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': [
'security/ir.model.access.csv',
"category" : "Generic Modules/Inventory Control",
"description": """
Product extension. This module adds:
- * Last purchase order for each product supplier
- * New functional field: Available stock (real+outgoing stock)
- * 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
+ * Computes standard price from the BoM of the product with a button on the product variant based
+ on the materials in the BoM and the work centers. It can create the necessary accounting entries when necessary.
""",
"init_xml" : [],
"demo_xml" : [],
testdict = {}
for prod_id in ids:
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:
# In recursive mode, it will first compute the prices of child boms
if recursive:
name: Gate B
usage: internal
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