[FIX] stock: backport fixes from master
authorChristophe Simonis <chs@odoo.com>
Tue, 1 Jul 2014 15:11:46 +0000 (17:11 +0200)
committerChristophe Simonis <chs@odoo.com>
Tue, 1 Jul 2014 15:11:46 +0000 (17:11 +0200)
addons/stock/security/ir.model.access.csv
addons/stock/security/stock_security.xml
addons/stock/stock.py

index 9ce5587..8a94f02 100644 (file)
@@ -60,7 +60,7 @@ access_stock_location_path_internal_user,stock location path internal user,model
 access_stock_location_path_sale_manager,stock.location.path partner salemanager,model_stock_location_path,base.group_sale_manager,1,1,1,1
 access_stock_location_path_stock_user,stock.location.path stock user,model_stock_location_path,stock.group_stock_user,1,1,1,1
 access_stock_location_path,stock.location.path,model_stock_location_path,base.group_sale_salesman,1,0,0,0
-access_stock_location_route,stock.location.route,model_stock_location_route,stock.group_stock_manager,1,1,1,1
+access_stock_location_route_stock_manager,stock.location.route,model_stock_location_route,stock.group_stock_manager,1,1,1,1
 access_stock_location_route,stock.location.route,model_stock_location_route,base.group_user,1,0,0,0
 access_procurement_rule,procurement.rule.flow,model_procurement_rule,base.group_sale_salesman,1,0,0,0
 access_procurement_rule_internal,procurement.rule.flow internal,model_procurement_rule,base.group_user,1,0,0,0
index f44d354..044ff13 100644 (file)
@@ -50,7 +50,7 @@
         <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
     </record>
     
-    <record model="ir.rule" id="stock_picking_rule">
+    <record model="ir.rule" id="stock_picking_type_rule">
         <field name="name">Stock Picking Type multi-company</field>
         <field name="model_id" search="[('model','=','stock.picking.type')]" model="ir.model"/>
         <field name="global" eval="True"/>
index d6d28c9..acb228b 100644 (file)
@@ -1248,6 +1248,7 @@ class stock_picking(osv.osv):
         '''
         move_obj = self.pool.get('stock.move')
         operation_obj = self.pool.get('stock.pack.operation')
+        moves = []
         for op in picking.pack_operation_ids:
             for product_id, remaining_qty in operation_obj._get_remaining_prod_quantities(cr, uid, op, context=context).items():
                 if remaining_qty > 0:
@@ -1260,9 +1261,12 @@ class stock_picking(osv.osv):
                         'product_uom': product.uom_id.id,
                         'product_uom_qty': remaining_qty,
                         'name': _('Extra Move: ') + product.name,
-                        'state': 'confirmed',
+                        'state': 'draft',
                     }
-                    move_obj.create(cr, uid, vals, context=context)
+                    moves.append(move_obj.create(cr, uid, vals, context=context))
+        if moves:
+            move_obj.action_confirm(cr, uid, moves, context=context)
+        return moves
 
     def rereserve_quants(self, cr, uid, picking, move_ids=[], context=None):
         """ Unreserve quants then try to reassign quants."""
@@ -1289,11 +1293,13 @@ class stock_picking(osv.osv):
             else:
                 need_rereserve, all_op_processed = self.picking_recompute_remaining_quantities(cr, uid, picking, context=context)
                 #create extra moves in the picking (unexpected product moves coming from pack operations)
+                todo_move_ids = []
                 if not all_op_processed:
-                    self._create_extra_moves(cr, uid, picking, context=context)
+                    todo_move_ids += self._create_extra_moves(cr, uid, picking, context=context)
+                    
                 picking.refresh()
                 #split move lines eventually
-                todo_move_ids = []
+                
                 toassign_move_ids = []
                 for move in picking.move_lines:
                     remaining_qty = move.remaining_qty
@@ -1371,7 +1377,7 @@ class stock_picking(osv.osv):
                     op = operation
                     if (operation.qty_done < operation.product_qty):
                         new_operation = stock_operation_obj.copy(cr, uid, operation.id, {'product_qty': operation.qty_done,'qty_done': operation.qty_done}, context=context)
-                        stock_operation_obj.write(cr, uid, operation.id, {'product_qty': operation.product_qty - operation.qty_done,'qty_done': 0}, context=context)
+                        stock_operation_obj.write(cr, uid, operation.id, {'product_qty': operation.product_qty - operation.qty_done,'qty_done': 0, 'lot_id': False}, context=context)
                         op = stock_operation_obj.browse(cr, uid, new_operation, context=context)
                     pack_operation_ids.append(op.id)
                     for record in op.linked_move_operation_ids:
@@ -1783,7 +1789,7 @@ class stock_move(osv.osv):
             'move_dest_id': move.id,
             'group_id': group_id,
             'route_ids': [(4, x.id) for x in move.route_ids],
-            'warehouse_id': move.warehouse_id and move.warehouse_id.id or False,
+            'warehouse_id': move.warehouse_id.id or (move.picking_type_id and move.picking_type_id.warehouse_id.id or False),
             'priority': move.priority,
         }
 
@@ -3108,63 +3114,23 @@ class stock_warehouse(osv.osv):
         pull_obj.write(cr, uid, warehouse.mto_pull_id.id, mto_pull_vals, context=context)
         return True
 
-    def create(self, cr, uid, vals, context=None):
-        if context is None:
-            context = {}
-        if vals is None:
-            vals = {}
-        data_obj = self.pool.get('ir.model.data')
+    def create_sequences_and_picking_types(self, cr, uid, warehouse, context=None):
         seq_obj = self.pool.get('ir.sequence')
         picking_type_obj = self.pool.get('stock.picking.type')
-        location_obj = self.pool.get('stock.location')
-
-        #create view location for warehouse
-        wh_loc_id = location_obj.create(cr, uid, {
-                'name': _(vals.get('code')),
-                'usage': 'view',
-                'location_id': data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_locations')[1]
-            }, context=context)
-        vals['view_location_id'] = wh_loc_id
-        #create all location
-        def_values = self.default_get(cr, uid, {'reception_steps', 'delivery_steps'})
-        reception_steps = vals.get('reception_steps',  def_values['reception_steps'])
-        delivery_steps = vals.get('delivery_steps', def_values['delivery_steps'])
-        context_with_inactive = context.copy()
-        context_with_inactive['active_test'] = False
-        sub_locations = [
-            {'name': _('Stock'), 'active': True, 'field': 'lot_stock_id'},
-            {'name': _('Input'), 'active': reception_steps != 'one_step', 'field': 'wh_input_stock_loc_id'},
-            {'name': _('Quality Control'), 'active': reception_steps == 'three_steps', 'field': 'wh_qc_stock_loc_id'},
-            {'name': _('Output'), 'active': delivery_steps != 'ship_only', 'field': 'wh_output_stock_loc_id'},
-            {'name': _('Packing Zone'), 'active': delivery_steps == 'pick_pack_ship', 'field': 'wh_pack_stock_loc_id'},
-        ]
-        for values in sub_locations:
-            location_id = location_obj.create(cr, uid, {
-                'name': values['name'],
-                'usage': 'internal',
-                'location_id': wh_loc_id,
-                'active': values['active'],
-            }, context=context_with_inactive)
-            vals[values['field']] = location_id
-
         #create new sequences
-        in_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence in'), 'prefix': vals.get('code', '') + '/IN/', 'padding': 5}, context=context)
-        out_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence out'), 'prefix': vals.get('code', '') + '/OUT/', 'padding': 5}, context=context)
-        pack_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence packing'), 'prefix': vals.get('code', '') + '/PACK/', 'padding': 5}, context=context)
-        pick_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence picking'), 'prefix': vals.get('code', '') + '/PICK/', 'padding': 5}, context=context)
-        int_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': vals.get('name', '') + _(' Sequence internal'), 'prefix': vals.get('code', '') + '/INT/', 'padding': 5}, context=context)
-
-        #create WH
-        new_id = super(stock_warehouse, self).create(cr, uid, vals=vals, context=context)
+        in_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': warehouse.name + _(' Sequence in'), 'prefix': warehouse.code + '/IN/', 'padding': 5}, context=context)
+        out_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': warehouse.name + _(' Sequence out'), 'prefix': warehouse.code + '/OUT/', 'padding': 5}, context=context)
+        pack_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': warehouse.name + _(' Sequence packing'), 'prefix': warehouse.code + '/PACK/', 'padding': 5}, context=context)
+        pick_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': warehouse.name + _(' Sequence picking'), 'prefix': warehouse.code + '/PICK/', 'padding': 5}, context=context)
+        int_seq_id = seq_obj.create(cr, SUPERUSER_ID, values={'name': warehouse.name + _(' Sequence internal'), 'prefix': warehouse.code + '/INT/', 'padding': 5}, context=context)
 
-        warehouse = self.browse(cr, uid, new_id, context=context)
         wh_stock_loc = warehouse.lot_stock_id
         wh_input_stock_loc = warehouse.wh_input_stock_loc_id
         wh_output_stock_loc = warehouse.wh_output_stock_loc_id
         wh_pack_stock_loc = warehouse.wh_pack_stock_loc_id
 
         #fetch customer and supplier locations, for references
-        customer_loc, supplier_loc = self._get_partner_locations(cr, uid, new_id, context=context)
+        customer_loc, supplier_loc = self._get_partner_locations(cr, uid, warehouse.id, context=context)
 
         #create in, out, internal picking types for warehouse
         input_loc = wh_input_stock_loc
@@ -3191,7 +3157,7 @@ class stock_warehouse(osv.osv):
 
         in_type_id = picking_type_obj.create(cr, uid, vals={
             'name': _('Receptions'),
-            'warehouse_id': new_id,
+            'warehouse_id': warehouse.id,
             'code': 'incoming',
             'sequence_id': in_seq_id,
             'default_location_src_id': supplier_loc.id,
@@ -3200,7 +3166,7 @@ class stock_warehouse(osv.osv):
             'color': color}, context=context)
         out_type_id = picking_type_obj.create(cr, uid, vals={
             'name': _('Delivery Orders'),
-            'warehouse_id': new_id,
+            'warehouse_id': warehouse.id,
             'code': 'outgoing',
             'sequence_id': out_seq_id,
             'return_picking_type_id': in_type_id,
@@ -3211,7 +3177,7 @@ class stock_warehouse(osv.osv):
         picking_type_obj.write(cr, uid, [in_type_id], {'return_picking_type_id': out_type_id}, context=context)
         int_type_id = picking_type_obj.create(cr, uid, vals={
             'name': _('Internal Transfers'),
-            'warehouse_id': new_id,
+            'warehouse_id': warehouse.id,
             'code': 'internal',
             'sequence_id': int_seq_id,
             'default_location_src_id': wh_stock_loc.id,
@@ -3221,22 +3187,22 @@ class stock_warehouse(osv.osv):
             'color': color}, context=context)
         pack_type_id = picking_type_obj.create(cr, uid, vals={
             'name': _('Pack'),
-            'warehouse_id': new_id,
+            'warehouse_id': warehouse.id,
             'code': 'internal',
             'sequence_id': pack_seq_id,
             'default_location_src_id': wh_pack_stock_loc.id,
             'default_location_dest_id': output_loc.id,
-            'active': delivery_steps == 'pick_pack_ship',
+            'active': warehouse.delivery_steps == 'pick_pack_ship',
             'sequence': max_sequence + 3,
             'color': color}, context=context)
         pick_type_id = picking_type_obj.create(cr, uid, vals={
             'name': _('Pick'),
-            'warehouse_id': new_id,
+            'warehouse_id': warehouse.id,
             'code': 'internal',
             'sequence_id': pick_seq_id,
             'default_location_src_id': wh_stock_loc.id,
             'default_location_dest_id': wh_pack_stock_loc.id,
-            'active': delivery_steps != 'ship_only',
+            'active': warehouse.delivery_steps != 'ship_only',
             'sequence': max_sequence + 2,
             'color': color}, context=context)
 
@@ -3248,7 +3214,52 @@ class stock_warehouse(osv.osv):
             'pick_type_id': pick_type_id,
             'int_type_id': int_type_id,
         }
-        super(stock_warehouse, self).write(cr, uid, new_id, vals=vals, context=context)
+        super(stock_warehouse, self).write(cr, uid, warehouse.id, vals=vals, context=context)
+
+
+    def create(self, cr, uid, vals, context=None):
+        if context is None:
+            context = {}
+        if vals is None:
+            vals = {}
+        data_obj = self.pool.get('ir.model.data')
+        seq_obj = self.pool.get('ir.sequence')
+        picking_type_obj = self.pool.get('stock.picking.type')
+        location_obj = self.pool.get('stock.location')
+
+        #create view location for warehouse
+        wh_loc_id = location_obj.create(cr, uid, {
+                'name': _(vals.get('code')),
+                'usage': 'view',
+                'location_id': data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_locations')[1]
+            }, context=context)
+        vals['view_location_id'] = wh_loc_id
+        #create all location
+        def_values = self.default_get(cr, uid, {'reception_steps', 'delivery_steps'})
+        reception_steps = vals.get('reception_steps',  def_values['reception_steps'])
+        delivery_steps = vals.get('delivery_steps', def_values['delivery_steps'])
+        context_with_inactive = context.copy()
+        context_with_inactive['active_test'] = False
+        sub_locations = [
+            {'name': _('Stock'), 'active': True, 'field': 'lot_stock_id'},
+            {'name': _('Input'), 'active': reception_steps != 'one_step', 'field': 'wh_input_stock_loc_id'},
+            {'name': _('Quality Control'), 'active': reception_steps == 'three_steps', 'field': 'wh_qc_stock_loc_id'},
+            {'name': _('Output'), 'active': delivery_steps != 'ship_only', 'field': 'wh_output_stock_loc_id'},
+            {'name': _('Packing Zone'), 'active': delivery_steps == 'pick_pack_ship', 'field': 'wh_pack_stock_loc_id'},
+        ]
+        for values in sub_locations:
+            location_id = location_obj.create(cr, uid, {
+                'name': values['name'],
+                'usage': 'internal',
+                'location_id': wh_loc_id,
+                'active': values['active'],
+            }, context=context_with_inactive)
+            vals[values['field']] = location_id
+
+        #create WH
+        new_id = super(stock_warehouse, self).create(cr, uid, vals=vals, context=context)
+        warehouse = self.browse(cr, uid, new_id, context=context)
+        self.create_sequences_and_picking_types(cr, uid, warehouse, context=context)
         warehouse.refresh()
 
         #create routes and push/pull rules
@@ -3292,7 +3303,8 @@ class stock_warehouse(osv.osv):
             for push in route.push_ids:
                 push_obj.write(cr, uid, push.id, {'name': pull.name.replace(warehouse.name, name, 1)}, context=context)
         #change the mto pull rule name
-        pull_obj.write(cr, uid, warehouse.mto_pull_id.id, {'name': warehouse.mto_pull_id.name.replace(warehouse.name, name, 1)}, context=context)
+        if warehouse.mto_pull_id.id:
+            pull_obj.write(cr, uid, warehouse.mto_pull_id.id, {'name': warehouse.mto_pull_id.name.replace(warehouse.name, name, 1)}, context=context)
 
     def _check_delivery_resupply(self, cr, uid, warehouse, new_location, change_to_multiple, context=None):
         """ Will check if the resupply routes from this warehouse follow the changes of number of delivery steps """
@@ -3374,11 +3386,12 @@ class stock_warehouse(osv.osv):
                 if vals.get('name'):
                     name = vals.get('name', warehouse.name)
                 self._handle_renaming(cr, uid, warehouse, name, vals.get('code', warehouse.code), context=context_with_inactive)
-                seq_obj.write(cr, uid, warehouse.in_type_id.sequence_id.id, {'name': name + _(' Sequence in'), 'prefix': vals.get('code', warehouse.code) + '\IN\\'}, context=context)
-                seq_obj.write(cr, uid, warehouse.out_type_id.sequence_id.id, {'name': name + _(' Sequence out'), 'prefix': vals.get('code', warehouse.code) + '\OUT\\'}, context=context)
-                seq_obj.write(cr, uid, warehouse.pack_type_id.sequence_id.id, {'name': name + _(' Sequence packing'), 'prefix': vals.get('code', warehouse.code) + '\PACK\\'}, context=context)
-                seq_obj.write(cr, uid, warehouse.pick_type_id.sequence_id.id, {'name': name + _(' Sequence picking'), 'prefix': vals.get('code', warehouse.code) + '\PICK\\'}, context=context)
-                seq_obj.write(cr, uid, warehouse.int_type_id.sequence_id.id, {'name': name + _(' Sequence internal'), 'prefix': vals.get('code', warehouse.code) + '\INT\\'}, context=context)
+                if warehouse.in_type_id:
+                    seq_obj.write(cr, uid, warehouse.in_type_id.sequence_id.id, {'name': name + _(' Sequence in'), 'prefix': vals.get('code', warehouse.code) + '\IN\\'}, context=context)
+                    seq_obj.write(cr, uid, warehouse.out_type_id.sequence_id.id, {'name': name + _(' Sequence out'), 'prefix': vals.get('code', warehouse.code) + '\OUT\\'}, context=context)
+                    seq_obj.write(cr, uid, warehouse.pack_type_id.sequence_id.id, {'name': name + _(' Sequence packing'), 'prefix': vals.get('code', warehouse.code) + '\PACK\\'}, context=context)
+                    seq_obj.write(cr, uid, warehouse.pick_type_id.sequence_id.id, {'name': name + _(' Sequence picking'), 'prefix': vals.get('code', warehouse.code) + '\PICK\\'}, context=context)
+                    seq_obj.write(cr, uid, warehouse.int_type_id.sequence_id.id, {'name': name + _(' Sequence internal'), 'prefix': vals.get('code', warehouse.code) + '\INT\\'}, context=context)
         if vals.get('resupply_wh_ids') and not vals.get('resupply_route_ids'):
             for cmd in vals.get('resupply_wh_ids'):
                 if cmd[0] == 6:
@@ -3818,8 +3831,8 @@ class stock_pack_operation(osv.osv):
             if pack_op.qty_done < pack_op.product_qty:
                 # we split the operation in two
                 op = self.copy(cr, uid, pack_op.id, {'product_qty': pack_op.qty_done, 'qty_done': pack_op.qty_done}, context=context)
-                self.write(cr, uid, ids, {'product_qty': pack_op.product_qty - pack_op.qty_done, 'qty_done': 0}, context=context)
-            processed_ids.append(op)      
+                self.write(cr, uid, [pack_op.id], {'product_qty': pack_op.product_qty - pack_op.qty_done, 'qty_done': 0, 'lot_id': False}, context=context)
+            processed_ids.append(op)
         self.write(cr, uid, processed_ids, {'processed': 'true'}, context=context)
 
     def create_and_assign_lot(self, cr, uid, id, name, context=None):
@@ -3828,10 +3841,16 @@ class stock_pack_operation(osv.osv):
         obj = self.browse(cr,uid,id,context)
         product_id = obj.product_id.id
         val = {'product_id': product_id}
+        new_lot_id = False
         if name:
+            lots = self.pool.get('stock.production.lot').search(cr, uid, ['&', ('name', '=', name), ('product_id', '=', product_id)], context=context)
+            if lots:
+                new_lot_id = lots[0]
             val.update({'name': name})
+
         if not obj.lot_id:
-            new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, val, context=context)
+            if not new_lot_id:
+                new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, val, context=context)
             self.write(cr, uid, id, {'lot_id': new_lot_id}, context=context)
 
     def _search_and_increment(self, cr, uid, picking_id, domain, filter_visible=False, visible_op_ids=False, increment=True, context=None):
@@ -3869,11 +3888,15 @@ class stock_pack_operation(osv.osv):
             self.write(cr, uid, [operation_id], {'qty_done': qty}, context=context)
         else:
             #no existing operation found for the given domain and picking => create a new one
+            picking_obj = self.pool.get("stock.picking")
+            picking = picking_obj.browse(cr, uid, picking_id, context=context)
             values = {
                 'picking_id': picking_id,
                 'product_qty': 0,
+                'location_id': picking.location_id.id, 
+                'location_dest_id': picking.location_dest_id.id,
                 'qty_done': 1,
-            }
+                }
             for key in domain:
                 var_name, dummy, value = key
                 uom_id = False
@@ -4072,11 +4095,11 @@ class stock_picking_type(osv.osv):
             tristates = []
             for picking in picking_obj.browse(cr, uid, picking_ids, context=context):
                 if picking.date_done > picking.date:
-                    tristates.insert(0, {'tooltip': picking.name + _(': Late'), 'value': -1})
+                    tristates.insert(0, {'tooltip': picking.name or '' + _(': Late'), 'value': -1})
                 elif picking.backorder_id:
-                    tristates.insert(0, {'tooltip': picking.name + _(': Backorder exists'), 'value': 0})
+                    tristates.insert(0, {'tooltip': picking.name or '' + _(': Backorder exists'), 'value': 0})
                 else:
-                    tristates.insert(0, {'tooltip': picking.name + _(': OK'), 'value': 1})
+                    tristates.insert(0, {'tooltip': picking.name or '' + _(': OK'), 'value': 1})
             res[picking_type_id] = tristates
         return res