2010-02-19 10:51:45 +00:00
# -*- coding: utf-8 -*-
##############################################################################
2010-06-13 22:35:25 +00:00
#
2010-02-19 10:51:45 +00:00
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
2010-06-13 22:35:25 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2010-02-19 10:51:45 +00:00
#
##############################################################################
from osv import fields , osv
2011-09-27 15:32:24 +00:00
from tools . translate import _
2011-03-09 12:24:21 +00:00
import decimal_precision as dp
2010-02-19 10:51:45 +00:00
class stock_move_consume ( osv . osv_memory ) :
_name = " stock.move.consume "
_description = " Consume Products "
2010-06-13 22:35:25 +00:00
2010-02-19 10:51:45 +00:00
_columns = {
2010-06-13 22:35:25 +00:00
' product_id ' : fields . many2one ( ' product.product ' , ' Product ' , required = True , select = True ) ,
2012-04-25 12:09:08 +00:00
' product_qty ' : fields . float ( ' Quantity ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) , required = True ) ,
' product_uom ' : fields . many2one ( ' product.uom ' , ' Product Unit of Measure ' , required = True ) ,
2010-02-23 05:34:00 +00:00
' location_id ' : fields . many2one ( ' stock.location ' , ' Location ' , required = True )
2010-03-17 07:56:05 +00:00
}
2010-02-19 10:51:45 +00:00
2011-12-21 11:38:22 +00:00
#TOFIX: product_uom should not have differemt category of default UOM of product. Qty should be convert into UOM of original move line before going in consume and scrap
2010-03-22 12:16:37 +00:00
def default_get ( self , cr , uid , fields , context = None ) :
2010-05-26 12:59:30 +00:00
""" Get default values
@param self : The object pointer .
@param cr : A database cursor
@param uid : ID of the user currently logged in
2010-06-13 22:35:25 +00:00
@param fields : List of fields for default value
@param context : A standard dictionary
2010-05-26 12:59:30 +00:00
@return : default values of fields
2010-03-16 06:46:43 +00:00
"""
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2010-06-13 22:35:25 +00:00
res = super ( stock_move_consume , self ) . default_get ( cr , uid , fields , context = context )
2010-02-19 10:51:45 +00:00
move = self . pool . get ( ' stock.move ' ) . browse ( cr , uid , context [ ' active_id ' ] , context = context )
2010-03-19 07:20:12 +00:00
if ' product_id ' in fields :
2010-06-13 22:35:25 +00:00
res . update ( { ' product_id ' : move . product_id . id } )
2010-03-19 07:20:12 +00:00
if ' product_uom ' in fields :
2010-06-13 22:35:25 +00:00
res . update ( { ' product_uom ' : move . product_uom . id } )
2010-03-19 07:20:12 +00:00
if ' product_qty ' in fields :
2010-05-04 11:14:19 +00:00
res . update ( { ' product_qty ' : move . product_qty } )
if ' location_id ' in fields :
res . update ( { ' location_id ' : move . location_id . id } )
2010-06-13 22:35:25 +00:00
return res
2010-11-22 10:37:53 +00:00
def do_move_consume ( self , cr , uid , ids , context = None ) :
2010-05-26 12:59:30 +00:00
""" To move consumed products
@param self : The object pointer .
@param cr : A database cursor
@param uid : ID of the user currently logged in
2010-06-13 22:35:25 +00:00
@param ids : the ID or list of IDs if we want more than one
@param context : A standard dictionary
@return :
"""
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2010-02-19 10:51:45 +00:00
move_obj = self . pool . get ( ' stock.move ' )
2010-02-23 05:34:00 +00:00
move_ids = context [ ' active_ids ' ]
2011-03-15 15:03:48 +00:00
for data in self . browse ( cr , uid , ids , context = context ) :
2010-06-13 22:35:25 +00:00
move_obj . action_consume ( cr , uid , move_ids ,
2011-03-15 15:03:48 +00:00
data . product_qty , data . location_id . id ,
2010-02-23 05:34:00 +00:00
context = context )
2010-12-28 10:41:38 +00:00
return { ' type ' : ' ir.actions.act_window_close ' }
2010-02-19 10:51:45 +00:00
stock_move_consume ( )
class stock_move_scrap ( osv . osv_memory ) :
_name = " stock.move.scrap "
_description = " Scrap Products "
_inherit = " stock.move.consume "
2010-06-13 22:35:25 +00:00
2010-02-19 10:51:45 +00:00
_defaults = {
2010-05-04 11:14:19 +00:00
' location_id ' : lambda * x : False
2010-02-23 05:34:00 +00:00
}
2010-02-19 10:51:45 +00:00
2010-05-04 11:14:19 +00:00
def default_get ( self , cr , uid , fields , context = None ) :
2010-05-26 12:59:30 +00:00
""" Get default values
@param self : The object pointer .
@param cr : A database cursor
@param uid : ID of the user currently logged in
2010-06-13 22:35:25 +00:00
@param fields : List of fields for default value
@param context : A standard dictionary
2010-05-26 12:59:30 +00:00
@return : default values of fields
2010-05-04 11:14:19 +00:00
"""
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2010-06-13 22:35:25 +00:00
res = super ( stock_move_consume , self ) . default_get ( cr , uid , fields , context = context )
2010-05-04 11:14:19 +00:00
move = self . pool . get ( ' stock.move ' ) . browse ( cr , uid , context [ ' active_id ' ] , context = context )
location_obj = self . pool . get ( ' stock.location ' )
2010-05-06 12:16:04 +00:00
scrpaed_location_ids = location_obj . search ( cr , uid , [ ( ' scrap_location ' , ' = ' , True ) ] )
2010-06-13 22:35:25 +00:00
2010-05-04 11:14:19 +00:00
if ' product_id ' in fields :
2010-06-13 22:35:25 +00:00
res . update ( { ' product_id ' : move . product_id . id } )
2010-05-04 11:14:19 +00:00
if ' product_uom ' in fields :
2010-06-13 22:35:25 +00:00
res . update ( { ' product_uom ' : move . product_uom . id } )
2010-05-04 11:14:19 +00:00
if ' product_qty ' in fields :
res . update ( { ' product_qty ' : move . product_qty } )
if ' location_id ' in fields :
if scrpaed_location_ids :
res . update ( { ' location_id ' : scrpaed_location_ids [ 0 ] } )
else :
res . update ( { ' location_id ' : False } )
2010-06-13 22:35:25 +00:00
2010-05-04 11:14:19 +00:00
return res
2010-06-13 22:35:25 +00:00
2010-11-22 10:37:53 +00:00
def move_scrap ( self , cr , uid , ids , context = None ) :
2010-08-31 06:54:27 +00:00
""" To move scrapped products
2010-05-26 12:59:30 +00:00
@param self : The object pointer .
@param cr : A database cursor
@param uid : ID of the user currently logged in
2010-06-13 22:35:25 +00:00
@param ids : the ID or list of IDs if we want more than one
@param context : A standard dictionary
@return :
"""
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2010-06-13 22:35:25 +00:00
move_obj = self . pool . get ( ' stock.move ' )
2010-02-23 05:34:00 +00:00
move_ids = context [ ' active_ids ' ]
2011-03-24 13:23:58 +00:00
for data in self . browse ( cr , uid , ids ) :
2010-06-13 22:35:25 +00:00
move_obj . action_scrap ( cr , uid , move_ids ,
2011-03-24 13:23:58 +00:00
data . product_qty , data . location_id . id ,
2010-02-23 05:34:00 +00:00
context = context )
2010-12-28 10:41:38 +00:00
return { ' type ' : ' ir.actions.act_window_close ' }
2010-02-19 10:51:45 +00:00
2010-02-19 13:44:55 +00:00
stock_move_scrap ( )
2010-03-05 10:08:13 +00:00
class split_in_production_lot ( osv . osv_memory ) :
_name = " stock.move.split "
2012-05-09 13:24:01 +00:00
_description = " Split in Serial Numbers "
2010-06-13 22:35:25 +00:00
2010-03-22 12:16:37 +00:00
def default_get ( self , cr , uid , fields , context = None ) :
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2010-06-13 22:35:25 +00:00
res = super ( split_in_production_lot , self ) . default_get ( cr , uid , fields , context = context )
2010-06-18 09:53:21 +00:00
if context . get ( ' active_id ' ) :
move = self . pool . get ( ' stock.move ' ) . browse ( cr , uid , context [ ' active_id ' ] , context = context )
if ' product_id ' in fields :
res . update ( { ' product_id ' : move . product_id . id } )
if ' product_uom ' in fields :
res . update ( { ' product_uom ' : move . product_uom . id } )
if ' qty ' in fields :
res . update ( { ' qty ' : move . product_qty } )
if ' use_exist ' in fields :
res . update ( { ' use_exist ' : ( move . picking_id and move . picking_id . type == ' out ' and True ) or False } )
2011-09-19 10:35:23 +00:00
if ' location_id ' in fields :
res . update ( { ' location_id ' : move . location_id . id } )
2010-03-19 07:20:12 +00:00
return res
2010-06-13 22:35:25 +00:00
2010-02-19 13:44:55 +00:00
_columns = {
2012-04-25 12:09:08 +00:00
' qty ' : fields . float ( ' Quantity ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) ) ,
2010-02-19 13:44:55 +00:00
' product_id ' : fields . many2one ( ' product.product ' , ' Product ' , required = True , select = True ) ,
2012-04-25 12:09:08 +00:00
' product_uom ' : fields . many2one ( ' product.uom ' , ' Unit of Measure ' ) ,
2012-05-09 13:24:01 +00:00
' line_ids ' : fields . one2many ( ' stock.move.split.lines ' , ' wizard_id ' , ' Serial Numbers ' ) ,
' line_exist_ids ' : fields . one2many ( ' stock.move.split.lines ' , ' wizard_exist_id ' , ' Serial Numbers ' ) ,
2010-09-06 11:48:17 +00:00
' use_exist ' : fields . boolean ( ' Existing Lots ' , help = " Check this option to select existing lots in the list below, otherwise you should enter new ones line by line. " ) ,
2011-09-19 10:35:23 +00:00
' location_id ' : fields . many2one ( ' stock.location ' , ' Source Location ' )
2010-02-23 05:34:00 +00:00
}
2010-06-13 22:35:25 +00:00
2010-02-19 13:44:55 +00:00
def split_lot ( self , cr , uid , ids , context = None ) :
2011-09-27 16:52:19 +00:00
""" To split a lot """
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2011-09-27 15:32:24 +00:00
res = self . split ( cr , uid , ids , context . get ( ' active_ids ' ) , context = context )
2010-12-28 10:41:38 +00:00
return { ' type ' : ' ir.actions.act_window_close ' }
2010-02-19 13:44:55 +00:00
2010-02-23 05:34:00 +00:00
def split ( self , cr , uid , ids , move_ids , context = None ) :
2012-05-09 13:24:01 +00:00
""" To split stock moves into serial numbers
2011-09-27 16:52:19 +00:00
: param move_ids : the ID or list of IDs of stock move we want to split
2010-06-13 22:35:25 +00:00
"""
2010-11-19 14:21:59 +00:00
if context is None :
context = { }
2011-09-27 16:52:19 +00:00
assert context . get ( ' active_model ' ) == ' stock.move ' , \
' Incorrect use of the stock move split wizard '
2010-11-22 10:53:10 +00:00
inventory_id = context . get ( ' inventory_id ' , False )
2010-02-23 05:34:00 +00:00
prodlot_obj = self . pool . get ( ' stock.production.lot ' )
2010-11-19 14:21:59 +00:00
inventory_obj = self . pool . get ( ' stock.inventory ' )
2010-02-23 05:34:00 +00:00
move_obj = self . pool . get ( ' stock.move ' )
2010-06-13 22:35:25 +00:00
new_move = [ ]
2010-11-22 10:37:53 +00:00
for data in self . browse ( cr , uid , ids , context = context ) :
for move in move_obj . browse ( cr , uid , move_ids , context = context ) :
2010-02-23 05:34:00 +00:00
move_qty = move . product_qty
quantity_rest = move . product_qty
uos_qty_rest = move . product_uos_qty
2010-06-13 22:35:25 +00:00
new_move = [ ]
2010-06-10 08:59:12 +00:00
if data . use_exist :
lines = [ l for l in data . line_exist_ids if l ]
else :
lines = [ l for l in data . line_ids if l ]
2012-01-06 10:21:31 +00:00
total_move_qty = 0.0
2010-06-10 08:59:12 +00:00
for line in lines :
2010-02-23 05:34:00 +00:00
quantity = line . quantity
2012-01-06 10:21:31 +00:00
total_move_qty + = quantity
if total_move_qty > move_qty :
2012-05-09 13:24:01 +00:00
raise osv . except_osv ( _ ( ' Processing Error ' ) , _ ( ' Serial number quantity %d of %s is larger than available quantity ( %d ) ! ' ) \
2012-01-11 14:39:56 +00:00
% ( total_move_qty , move . product_id . name , move_qty ) )
2010-02-23 05:34:00 +00:00
if quantity < = 0 or move_qty == 0 :
continue
quantity_rest - = quantity
uos_qty = quantity / move_qty * move . product_uos_qty
uos_qty_rest = quantity_rest / move_qty * move . product_uos_qty
2010-06-07 14:26:20 +00:00
if quantity_rest < 0 :
2010-02-23 05:34:00 +00:00
quantity_rest = quantity
2011-09-27 15:32:24 +00:00
self . pool . get ( ' stock.move ' ) . log ( cr , uid , move . id , _ ( ' Unable to assign all lots to this move! ' ) )
return False
2010-02-23 05:34:00 +00:00
default_val = {
2010-06-13 22:35:25 +00:00
' product_qty ' : quantity ,
' product_uos_qty ' : uos_qty ,
2010-06-14 11:49:11 +00:00
' state ' : move . state
2010-02-23 05:34:00 +00:00
}
2010-06-07 14:26:20 +00:00
if quantity_rest > 0 :
2010-11-24 10:50:29 +00:00
current_move = move_obj . copy ( cr , uid , move . id , default_val , context = context )
2010-11-24 11:27:43 +00:00
if inventory_id and current_move :
inventory_obj . write ( cr , uid , inventory_id , { ' move_ids ' : [ ( 4 , current_move ) ] } , context = context )
2010-06-07 14:26:20 +00:00
new_move . append ( current_move )
2010-11-19 14:21:59 +00:00
2010-06-07 14:26:20 +00:00
if quantity_rest == 0 :
current_move = move . id
2010-02-23 05:34:00 +00:00
prodlot_id = False
2010-06-21 18:40:58 +00:00
if data . use_exist :
prodlot_id = line . prodlot_id . id
2010-02-23 05:34:00 +00:00
if not prodlot_id :
2010-06-21 18:40:58 +00:00
prodlot_id = prodlot_obj . create ( cr , uid , {
' name ' : line . name ,
' product_id ' : move . product_id . id } ,
context = context )
2010-11-19 14:21:59 +00:00
2010-06-15 20:20:04 +00:00
move_obj . write ( cr , uid , [ current_move ] , { ' prodlot_id ' : prodlot_id , ' state ' : move . state } )
2010-06-13 22:35:25 +00:00
2010-02-23 05:34:00 +00:00
update_val = { }
2010-06-13 22:35:25 +00:00
if quantity_rest > 0 :
2010-02-23 05:34:00 +00:00
update_val [ ' product_qty ' ] = quantity_rest
2010-06-13 22:35:25 +00:00
update_val [ ' product_uos_qty ' ] = uos_qty_rest
2010-06-15 20:20:04 +00:00
update_val [ ' state ' ] = move . state
2010-02-23 05:34:00 +00:00
move_obj . write ( cr , uid , [ move . id ] , update_val )
2010-11-19 14:21:59 +00:00
2010-02-23 05:34:00 +00:00
return new_move
2010-11-24 10:50:29 +00:00
2010-03-05 10:08:13 +00:00
split_in_production_lot ( )
2010-02-23 05:34:00 +00:00
2010-06-10 08:59:12 +00:00
class stock_move_split_lines_exist ( osv . osv_memory ) :
2011-09-27 16:52:19 +00:00
_name = " stock.move.split.lines "
_description = " Stock move Split lines "
2010-06-10 08:59:12 +00:00
_columns = {
2012-04-24 13:08:05 +00:00
' name ' : fields . char ( ' Serial Number ' , size = 64 ) ,
2012-04-25 12:09:08 +00:00
' quantity ' : fields . float ( ' Quantity ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) ) ,
2011-09-27 16:52:19 +00:00
' wizard_id ' : fields . many2one ( ' stock.move.split ' , ' Parent Wizard ' ) ,
' wizard_exist_id ' : fields . many2one ( ' stock.move.split ' , ' Parent Wizard (for existing lines) ' ) ,
2012-04-24 13:08:05 +00:00
' prodlot_id ' : fields . many2one ( ' stock.production.lot ' , ' Serial Number ' ) ,
2010-06-10 08:59:12 +00:00
}
_defaults = {
2011-05-02 18:46:43 +00:00
' quantity ' : 1.0 ,
2010-06-10 08:59:12 +00:00
}
2011-09-19 10:35:23 +00:00
def onchange_lot_id ( self , cr , uid , ids , prodlot_id = False , product_qty = False ,
loc_id = False , product_id = False , uom_id = False ) :
return self . pool . get ( ' stock.move ' ) . onchange_lot_id ( cr , uid , [ ] , prodlot_id , product_qty ,
loc_id , product_id , uom_id )
2011-11-22 08:51:38 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: