diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 6b7133b680a..7fe6b81f079 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -230,7 +230,7 @@ class mrp_bom(osv.osv): } _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. @@ -254,16 +254,18 @@ class mrp_bom(osv.osv): 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. @@ -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])) 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"): @@ -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."), '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."), @@ -645,7 +647,7 @@ class mrp_production(osv.osv): }} 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) @@ -694,7 +696,7 @@ class mrp_production(osv.osv): 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 diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index ec175273d10..0c17cd1cc76 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -62,8 +62,8 @@ class procurement_order(osv.osv): """ 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 @@ -84,8 +84,8 @@ class procurement_order(osv.osv): 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 diff --git a/addons/mrp/report/price.py b/addons/mrp/report/price.py index 9e818001d15..eafb8e146fe 100644 --- a/addons/mrp/report/price.py +++ b/addons/mrp/report/price.py @@ -144,7 +144,7 @@ class report_custom(report_rml): 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 = "%s" %(_("Cost Structure")) title += "%s" % (to_xml(product.name)) xml += "" + title + prod_header + "" diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py index 44eed63d029..2eee6e1cfdb 100644 --- a/addons/mrp/wizard/change_production_qty.py +++ b/addons/mrp/wizard/change_production_qty.py @@ -78,7 +78,7 @@ class change_production_qty(osv.osv_memory): 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}) diff --git a/addons/mrp/wizard/stock_move.py b/addons/mrp/wizard/stock_move.py index d615741845b..8ab75a7836b 100644 --- a/addons/mrp/wizard/stock_move.py +++ b/addons/mrp/wizard/stock_move.py @@ -62,7 +62,7 @@ class stock_move_consume(osv.osv_memory): 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) diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py index b67f7ebf5b5..043acb70c7d 100644 --- a/addons/mrp_operations/mrp_operations.py +++ b/addons/mrp_operations/mrp_operations.py @@ -123,7 +123,6 @@ class mrp_production_workcenter_line(osv.osv): 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: diff --git a/addons/mrp_operations/test/workcenter_operations.yml b/addons/mrp_operations/test/workcenter_operations.yml index a31c3fb05d2..d4533d6b3a5 100644 --- a/addons/mrp_operations/test/workcenter_operations.yml +++ b/addons/mrp_operations/test/workcenter_operations.yml @@ -79,7 +79,7 @@ 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) diff --git a/addons/procurement/__openerp__.py b/addons/procurement/__openerp__.py index 5ba078092db..fa3b58486b5 100644 --- a/addons/procurement/__openerp__.py +++ b/addons/procurement/__openerp__.py @@ -31,17 +31,22 @@ 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', diff --git a/addons/product_extended/__openerp__.py b/addons/product_extended/__openerp__.py index 3c2fc7581c6..9638dc9de11 100644 --- a/addons/product_extended/__openerp__.py +++ b/addons/product_extended/__openerp__.py @@ -27,10 +27,8 @@ "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" : [], diff --git a/addons/product_extended/product_extended.py b/addons/product_extended/product_extended.py index 14383704b34..4aecc29da12 100644 --- a/addons/product_extended/product_extended.py +++ b/addons/product_extended/product_extended.py @@ -36,7 +36,7 @@ class product_product(osv.osv): 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: diff --git a/addons/stock/stock_location_demo_cpu3.yml b/addons/stock/stock_location_demo_cpu3.yml index 65ab318df6d..c4323d65f9d 100644 --- a/addons/stock/stock_location_demo_cpu3.yml +++ b/addons/stock/stock_location_demo_cpu3.yml @@ -18,9 +18,3 @@ 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