[MERGE] merged from lp:~openerp/openobject-addons/trunk/
[odoo/odoo.git] / addons / mrp / mrp.py
index 716b191..2a46fc0 100644 (file)
@@ -189,6 +189,8 @@ class mrp_bom(osv.osv):
         'child_ids': fields.function(_child_compute,relation='mrp.bom', method=True, string="BoM Hierarchy", type='many2many'),
         'child_complete_ids': fields.function(_child_compute,relation='mrp.bom', method=True, string="BoM Hierarchy", type='many2many'),
         'company_id': fields.many2one('res.company','Company',required=True),
+        'multi_level_bom': fields.boolean('Multi-level BoM'),
+
     }
     _defaults = {
         'active': lambda *a: 1,
@@ -196,7 +198,8 @@ class mrp_bom(osv.osv):
         'product_qty': lambda *a: 1.0,
         'product_rounding': lambda *a: 1.0,
         'type': lambda *a: 'normal',
-        'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.bom', context=c)
+        'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.bom', context=c),
+        'multi_level_bom': lambda *a: 0, 
     }
     _order = "sequence"
     _sql_constraints = [
@@ -375,30 +378,7 @@ class one2many_domain(fields.one2many):
 class mrp_production(osv.osv):
     _name = 'mrp.production'
     _description = 'Production'
-    _date_name  = 'date_planned'
-
-    def _get_sale_order(self,cr,uid,ids,field_name=False):
-        move_obj=self.pool.get('stock.move')
-        def get_parent_move(move_id):
-            move = move_obj.browse(cr,uid,move_id)
-            if move.move_dest_id:
-                return get_parent_move(move.move_dest_id.id)
-            return move_id
-        productions=self.read(cr,uid,ids,['id','move_prod_id'])
-        res={}
-        for production in productions:
-            res[production['id']]=False
-            if production.get('move_prod_id',False):
-                parent_move_line=get_parent_move(production['move_prod_id'][0])
-                if parent_move_line:
-                    move = move_obj.browse(cr,uid,parent_move_line)
-                    #TODO: fix me sale module can not be used here,
-                    #as may be mrp can be installed without sale module
-                    if field_name=='name':
-                        res[production['id']]=move.sale_line_id and move.sale_line_id.order_id.name or False
-                    if field_name=='client_order_ref':
-                        res[production['id']]=move.sale_line_id and move.sale_line_id.order_id.client_order_ref or False
-        return res
+    _date_name  = 'date_planned'    
 
     def _production_calc(self, cr, uid, ids, prop, unknow_none, context={}):
         result = {}
@@ -424,11 +404,12 @@ class mrp_production(osv.osv):
             result[prod.id] = prod.date_planned[:10]
         return result
 
-    def _sale_name_calc(self, cr, uid, ids, prop, unknow_none, unknow_dict):
-        return self._get_sale_order(cr,uid,ids,field_name='name')
-
-    def _sale_ref_calc(self, cr, uid, ids, prop, unknow_none, unknow_dict):
-        return self._get_sale_order(cr,uid,ids,field_name='client_order_ref')
+    def _ref_calc(self, cr, uid, ids, field_names=None, arg=False, context={}):
+        res = {}
+        for f in field_names:
+            for order_id in ids:
+                res[order_id] = {f:False}
+        return res
 
     _columns = {
         'name': fields.char('Reference', size=64, required=True),
@@ -470,8 +451,8 @@ class mrp_production(osv.osv):
         'hour_total': fields.function(_production_calc, method=True, type='float', string='Total Hours', multi='workorder'),
         'cycle_total': fields.function(_production_calc, method=True, type='float', string='Total Cycles', multi='workorder'),
 
-        'sale_name': fields.function(_sale_name_calc, method=True, type='char', string='Sale Name', help='Indicate the name of sale order.'),
-        'sale_ref': fields.function(_sale_ref_calc, method=True, type='char', string='Sale Reference', help='Indicate the Customer Reference from sale order.'),
+        'sale_name': fields.function(_ref_calc, method=True, multi='sale_name', type='char', string='Sale Name', help='Indicate the name of sale order.'),
+        'sale_ref': fields.function(_ref_calc, method=True, multi='sale_ref', type='char', string='Sale Reference', help='Indicate the Customer Reference from sale order.'),
         'company_id': fields.many2one('res.company','Company',required=True),
     }
     _defaults = {
@@ -596,7 +577,23 @@ class mrp_production(osv.osv):
                res = False        
         return res
 
-    def do_produce(self, cr, uid, production_id, production_qty, production_mode, context=None):
+    def action_produce(self, cr, uid, production_id, production_qty, production_mode, context=None):
+        """ 
+             @summary: To produce final product base 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 self: The object pointer.
+             @param cr: A database cursor
+             @param uid: ID of the user currently logged in
+             @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)
         
@@ -604,6 +601,7 @@ class mrp_production(osv.osv):
         final_product_todo = []        
         
         if production_mode in ['consume','consume_produce']:
+            # To consume remaining qty of raw materials 
             consumed_products = {}
             produced_qty = 0
             for consumed_product in production.move_lines2:
@@ -628,6 +626,7 @@ class mrp_production(osv.osv):
                     stock_mov_obj.action_consume(cr, uid, [raw_product.id], rest_qty, production.location_src_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)
@@ -725,7 +724,9 @@ class mrp_production(osv.osv):
                     pick_type = 'out'
                 address_id = routing_loc.address_id and routing_loc.address_id.id or False
                 routing_loc = routing_loc.id
+            pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.'+pick_type)
             picking_id = self.pool.get('stock.picking').create(cr, uid, {
+                'name': pick_name,
                 'origin': (production.origin or '').split(':')[0] +':'+production.name,
                 'type': pick_type,
                 'move_type': 'one',
@@ -1112,7 +1113,21 @@ class mrp_procurement(osv.osv):
         return True
 
     def action_produce_assign_product(self, cr, uid, ids, context={}):
-        produce_id = False
+        """
+        @summary : This is action which call from workflow to assign production order to procuments
+        @return  : True
+        """
+        res = self.make_mo(cr, uid, ids, context=context)
+        res = res.values()
+        return len(res) and res[0] or 0 #TO CHECK: why workflow is generated error if return not integer value
+
+    def make_mo(self, cr, uid, ids, context={}):
+        """
+        @summary : Make Manufecturing(production) order from procurement
+        
+        @return : New created Production Orders procurement wise 
+        """
+        res = {}
         company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
         for procurement in self.browse(cr, uid, ids):
             res_id = procurement.move_id.id
@@ -1133,6 +1148,7 @@ class mrp_procurement(osv.osv):
                 'move_prod_id': res_id,
                 'company_id': procurement.company_id.id,
             })
+            res[procurement.id] = produce_id
             self.write(cr, uid, [procurement.id], {'state':'running'})
             bom_result = self.pool.get('mrp.production').action_compute(cr, uid,
                     [produce_id], properties=[x.id for x in procurement.property_ids])
@@ -1140,10 +1156,24 @@ class mrp_procurement(osv.osv):
             wf_service.trg_validate(uid, 'mrp.production', produce_id, 'button_confirm', cr)
             self.pool.get('stock.move').write(cr, uid, [res_id],
                     {'location_id':procurement.location_id.id})
-        return produce_id
-
+        return res
+    
     def action_po_assign(self, cr, uid, ids, context={}):
-        purchase_id = False
+        """
+        @summary : This is action which call from workflow to assign purchase order to procuments
+        @return  : True
+        """
+        res = self.make_po(cr, uid, ids, context=context)
+        res = res.values()
+        return len(res) and res[0] or 0 #TO CHECK: why workflow is generated error if return not integer value
+
+    def make_po(self, cr, uid, ids, context={}):
+        """
+        @summary : Make purchase order from procurement
+        
+        @return : New created Purchase Orders procurement wise
+        """
+        res = {}
         company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
         for procurement in self.browse(cr, uid, ids):
             res_id = procurement.move_id.id
@@ -1195,8 +1225,9 @@ class mrp_procurement(osv.osv):
                 'company_id': procurement.company_id.id,
                 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False
             })
+            res[procurement.id] = purchase_id
             self.write(cr, uid, [procurement.id], {'state':'running', 'purchase_id':purchase_id})
-        return purchase_id
+        return res
 
     def action_cancel(self, cr, uid, ids):
         todo = []