2009-10-14 11:15:34 +00:00
# -*- coding: utf-8 -*-
2006-12-07 13:41:40 +00:00
##############################################################################
#
2009-09-24 10:46:21 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2006-12-07 13:41:40 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# 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.
2006-12-07 13:41:40 +00:00
#
2008-11-03 19:18:56 +00:00
# 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
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2006-12-07 13:41:40 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2008-11-03 19:18:56 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2006-12-07 13:41:40 +00:00
#
##############################################################################
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
2012-12-17 15:23:03 +00:00
import openerp . addons . decimal_precision as dp
2008-12-08 17:08:40 +00:00
2008-09-07 23:24:39 +00:00
class product_product ( osv . osv ) :
2010-06-12 23:01:10 +00:00
_inherit = " product.product "
2010-03-25 12:08:31 +00:00
2012-05-22 07:02:28 +00:00
def _stock_move_count ( self , cr , uid , ids , field_name , arg , context = None ) :
2012-05-04 14:55:51 +00:00
res = dict ( [ ( id , { ' reception_count ' : 0 , ' delivery_count ' : 0 } ) for id in ids ] )
2012-05-22 07:02:28 +00:00
move_pool = self . pool . get ( ' stock.move ' )
2012-05-22 14:37:59 +00:00
moves = move_pool . read_group ( cr , uid , [
( ' product_id ' , ' in ' , ids ) ,
( ' picking_id.type ' , ' = ' , ' in ' ) ,
2012-09-03 17:54:10 +00:00
( ' state ' , ' in ' , ( ' confirmed ' , ' assigned ' , ' pending ' ) )
2012-05-22 14:37:59 +00:00
] , [ ' product_id ' ] , [ ' product_id ' ] )
for move in moves :
product_id = move [ ' product_id ' ] [ 0 ]
2012-05-22 14:54:33 +00:00
res [ product_id ] [ ' reception_count ' ] = move [ ' product_id_count ' ]
2012-05-22 14:37:59 +00:00
moves = move_pool . read_group ( cr , uid , [
( ' product_id ' , ' in ' , ids ) ,
( ' picking_id.type ' , ' = ' , ' out ' ) ,
2012-09-03 17:54:10 +00:00
( ' state ' , ' in ' , ( ' confirmed ' , ' assigned ' , ' pending ' ) )
2012-05-22 14:37:59 +00:00
] , [ ' product_id ' ] , [ ' product_id ' ] )
for move in moves :
product_id = move [ ' product_id ' ] [ 0 ]
2012-06-11 10:50:38 +00:00
res [ product_id ] [ ' delivery_count ' ] = move [ ' product_id_count ' ]
2012-05-04 14:55:51 +00:00
return res
2012-04-26 10:31:33 +00:00
2010-06-10 12:44:52 +00:00
def get_product_accounts ( self , cr , uid , product_id , context = None ) :
2010-05-27 05:45:34 +00:00
""" To get the stock input account, stock output account and stock journal related to product.
2010-07-06 11:56:32 +00:00
@param product_id : product id
2010-05-27 05:45:34 +00:00
@return : dictionary which contains information regarding stock input account , stock output account and stock journal
2010-06-10 12:44:52 +00:00
"""
2010-07-06 11:56:32 +00:00
if context is None :
context = { }
product_obj = self . pool . get ( ' product.product ' ) . browse ( cr , uid , product_id , context = context )
stock_input_acc = product_obj . property_stock_account_input and product_obj . property_stock_account_input . id or False
2010-05-27 05:45:34 +00:00
if not stock_input_acc :
stock_input_acc = product_obj . categ_id . property_stock_account_input_categ and product_obj . categ_id . property_stock_account_input_categ . id or False
2010-07-06 11:56:32 +00:00
2010-05-27 05:45:34 +00:00
stock_output_acc = product_obj . property_stock_account_output and product_obj . property_stock_account_output . id or False
if not stock_output_acc :
stock_output_acc = product_obj . categ_id . property_stock_account_output_categ and product_obj . categ_id . property_stock_account_output_categ . id or False
2010-03-25 12:08:31 +00:00
2010-05-27 05:45:34 +00:00
journal_id = product_obj . categ_id . property_stock_journal and product_obj . categ_id . property_stock_journal . id or False
2011-10-10 06:43:37 +00:00
account_valuation = product_obj . categ_id . property_stock_valuation_account_id and product_obj . categ_id . property_stock_valuation_account_id . id or False
2010-06-10 12:44:52 +00:00
return {
2010-07-06 11:56:32 +00:00
' stock_account_input ' : stock_input_acc ,
' stock_account_output ' : stock_output_acc ,
' stock_journal ' : journal_id ,
2011-10-10 06:43:37 +00:00
' property_stock_valuation_account_id ' : account_valuation
2010-07-06 11:56:32 +00:00
}
2010-05-27 07:10:12 +00:00
2010-11-22 10:37:53 +00:00
def do_change_standard_price ( self , cr , uid , ids , datas , context = None ) :
2010-05-26 12:59:30 +00:00
""" Changes the Standard Price of Product and creates an account move accordingly.
@param datas : dict . contain default datas like new_price , stock_output_account , stock_input_account , stock_journal
2010-07-06 11:56:32 +00:00
@param context : A standard dictionary
@return :
"""
2010-03-25 12:08:31 +00:00
location_obj = self . pool . get ( ' stock.location ' )
move_obj = self . pool . get ( ' account.move ' )
2010-07-06 11:56:32 +00:00
move_line_obj = self . pool . get ( ' account.move.line ' )
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2010-03-26 09:25:02 +00:00
2010-03-25 12:08:31 +00:00
new_price = datas . get ( ' new_price ' , 0.0 )
stock_output_acc = datas . get ( ' stock_output_account ' , False )
stock_input_acc = datas . get ( ' stock_input_account ' , False )
journal_id = datas . get ( ' stock_journal ' , False )
2010-07-06 11:56:32 +00:00
move_ids = [ ]
2010-06-12 23:01:10 +00:00
loc_ids = location_obj . search ( cr , uid , [ ( ' usage ' , ' = ' , ' internal ' ) ] )
2014-01-21 12:42:43 +00:00
for product in self . browse ( cr , uid , ids , context = context ) :
if product . valuation != ' real_time ' :
continue
account_valuation = product . categ_id . property_stock_valuation_account_id
account_valuation_id = account_valuation and account_valuation . id or False
if not account_valuation_id : raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' Specify valuation Account for Product Category: %s . ' ) % ( product . categ_id . name ) )
2010-11-22 10:37:53 +00:00
for location in location_obj . browse ( cr , uid , loc_ids , context = context ) :
2010-03-25 12:08:31 +00:00
c = context . copy ( )
c . update ( {
' location ' : location . id ,
' compute_child ' : False
2010-07-06 11:56:32 +00:00
} )
2014-04-29 12:42:56 +00:00
# qty_available depends of the location in the context
qty = self . read ( cr , uid , [ product . id ] , [ ' qty_available ' ] , context = c ) [ 0 ] [ ' qty_available ' ]
2010-07-06 11:56:32 +00:00
diff = product . standard_price - new_price
2012-07-12 06:25:39 +00:00
if not diff : raise osv . except_osv ( _ ( ' Error! ' ) , _ ( " No difference between standard price and new price! " ) )
2010-03-25 12:08:31 +00:00
if qty :
2010-07-06 11:56:32 +00:00
company_id = location . company_id and location . company_id . id or False
2012-07-25 10:30:41 +00:00
if not company_id : raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' Please specify company in Location. ' ) )
2010-03-26 09:25:02 +00:00
#
# Accounting Entries
#
if not journal_id :
journal_id = product . categ_id . property_stock_journal and product . categ_id . property_stock_journal . id or False
if not journal_id :
raise osv . except_osv ( _ ( ' Error! ' ) ,
2012-07-25 10:30:41 +00:00
_ ( ' Please define journal ' \
' on the product category: " %s " (id: %d ). ' ) % \
2010-03-26 09:25:02 +00:00
( product . categ_id . name ,
product . categ_id . id , ) )
2010-03-25 12:08:31 +00:00
move_id = move_obj . create ( cr , uid , {
2010-07-06 11:56:32 +00:00
' journal_id ' : journal_id ,
2010-03-25 12:08:31 +00:00
' company_id ' : company_id
2010-07-06 11:56:32 +00:00
} )
2010-03-25 12:08:31 +00:00
move_ids . append ( move_id )
2010-03-26 09:25:02 +00:00
if diff > 0 :
if not stock_input_acc :
2012-07-27 01:52:02 +00:00
stock_input_acc = product . \
2010-03-26 09:25:02 +00:00
property_stock_account_input . id
if not stock_input_acc :
stock_input_acc = product . categ_id . \
property_stock_account_input_categ . id
if not stock_input_acc :
raise osv . except_osv ( _ ( ' Error! ' ) ,
2012-07-25 10:30:41 +00:00
_ ( ' Please define stock input account ' \
' for this product: " %s " (id: %d ). ' ) % \
2010-03-26 09:25:02 +00:00
( product . name ,
product . id , ) )
2010-07-06 11:56:32 +00:00
amount_diff = qty * diff
2010-03-25 12:08:31 +00:00
move_line_obj . create ( cr , uid , {
' name ' : product . name ,
' account_id ' : stock_input_acc ,
' debit ' : amount_diff ,
' move_id ' : move_id ,
} )
move_line_obj . create ( cr , uid , {
2010-07-01 13:40:10 +00:00
' name ' : product . categ_id . name ,
2011-10-10 06:43:37 +00:00
' account_id ' : account_valuation_id ,
2010-03-25 12:08:31 +00:00
' credit ' : amount_diff ,
' move_id ' : move_id
} )
2010-07-06 11:56:32 +00:00
elif diff < 0 :
2010-03-26 09:25:02 +00:00
if not stock_output_acc :
2012-07-27 01:52:02 +00:00
stock_output_acc = product . \
2010-03-26 09:25:02 +00:00
property_stock_account_output . id
if not stock_output_acc :
stock_output_acc = product . categ_id . \
property_stock_account_output_categ . id
if not stock_output_acc :
raise osv . except_osv ( _ ( ' Error! ' ) ,
2012-07-25 10:30:41 +00:00
_ ( ' Please define stock output account ' \
' for this product: " %s " (id: %d ). ' ) % \
2010-03-26 09:25:02 +00:00
( product . name ,
product . id , ) )
2010-03-25 12:08:31 +00:00
amount_diff = qty * - diff
move_line_obj . create ( cr , uid , {
2010-08-13 12:20:05 +00:00
' name ' : product . name ,
' account_id ' : stock_output_acc ,
' credit ' : amount_diff ,
' move_id ' : move_id
2010-03-25 12:08:31 +00:00
} )
move_line_obj . create ( cr , uid , {
2010-08-13 12:20:05 +00:00
' name ' : product . categ_id . name ,
2011-10-10 06:43:37 +00:00
' account_id ' : account_valuation_id ,
2010-08-13 12:20:05 +00:00
' debit ' : amount_diff ,
' move_id ' : move_id
2010-07-06 11:56:32 +00:00
} )
2014-01-21 12:42:43 +00:00
self . write ( cr , uid , ids , { ' standard_price ' : new_price } )
2010-03-25 12:08:31 +00:00
2010-03-26 09:25:02 +00:00
return move_ids
2010-03-25 12:08:31 +00:00
2010-07-06 11:56:32 +00:00
def view_header_get ( self , cr , user , view_id , view_type , context = None ) :
if context is None :
context = { }
2008-09-23 14:24:03 +00:00
res = super ( product_product , self ) . view_header_get ( cr , user , view_id , view_type , context )
if res : return res
2010-07-07 09:05:22 +00:00
if ( context . get ( ' active_id ' , False ) ) and ( context . get ( ' active_model ' ) == ' stock.location ' ) :
return _ ( ' Products: ' ) + self . pool . get ( ' stock.location ' ) . browse ( cr , user , context [ ' active_id ' ] , context ) . name
2008-09-23 14:24:03 +00:00
return res
2010-05-26 12:59:30 +00:00
def get_product_available ( self , cr , uid , ids , context = None ) :
""" Finds whether product is available or not in particular warehouse.
@return : Dictionary of values
"""
2010-05-25 12:03:36 +00:00
if context is None :
2008-10-31 14:09:59 +00:00
context = { }
2011-06-02 06:55:59 +00:00
location_obj = self . pool . get ( ' stock.location ' )
warehouse_obj = self . pool . get ( ' stock.warehouse ' )
2012-01-10 22:52:13 +00:00
shop_obj = self . pool . get ( ' sale.shop ' )
2011-06-02 06:55:59 +00:00
2010-05-25 12:03:36 +00:00
states = context . get ( ' states ' , [ ] )
what = context . get ( ' what ' , ( ) )
2008-09-23 13:24:11 +00:00
if not ids :
ids = self . search ( cr , uid , [ ] )
res = { } . fromkeys ( ids , 0.0 )
if not ids :
2008-09-23 14:24:03 +00:00
return res
2008-09-23 13:24:11 +00:00
if context . get ( ' shop ' , False ) :
2012-01-10 22:52:13 +00:00
warehouse_id = shop_obj . read ( cr , uid , int ( context [ ' shop ' ] ) , [ ' warehouse_id ' ] ) [ ' warehouse_id ' ] [ 0 ]
if warehouse_id :
context [ ' warehouse ' ] = warehouse_id
2008-09-23 13:24:11 +00:00
if context . get ( ' warehouse ' , False ) :
2012-01-10 22:52:13 +00:00
lot_id = warehouse_obj . read ( cr , uid , int ( context [ ' warehouse ' ] ) , [ ' lot_stock_id ' ] ) [ ' lot_stock_id ' ] [ 0 ]
if lot_id :
context [ ' location ' ] = lot_id
2008-09-23 13:24:11 +00:00
if context . get ( ' location ' , False ) :
2008-09-25 09:30:39 +00:00
if type ( context [ ' location ' ] ) == type ( 1 ) :
location_ids = [ context [ ' location ' ] ]
2010-06-12 23:01:10 +00:00
elif type ( context [ ' location ' ] ) in ( type ( ' ' ) , type ( u ' ' ) ) :
2011-06-02 06:55:59 +00:00
location_ids = location_obj . search ( cr , uid , [ ( ' name ' , ' ilike ' , context [ ' location ' ] ) ] , context = context )
2008-09-25 09:30:39 +00:00
else :
location_ids = context [ ' location ' ]
2008-09-23 13:24:11 +00:00
else :
2009-06-24 06:11:42 +00:00
location_ids = [ ]
2011-06-02 06:55:59 +00:00
wids = warehouse_obj . search ( cr , uid , [ ] , context = context )
2013-04-17 13:20:21 +00:00
if not wids :
return res
2011-06-02 06:55:59 +00:00
for w in warehouse_obj . browse ( cr , uid , wids , context = context ) :
2009-06-24 06:11:42 +00:00
location_ids . append ( w . lot_stock_id . id )
2008-09-23 13:24:11 +00:00
# build the list of ids of children of the location given by id
2009-01-28 14:29:42 +00:00
if context . get ( ' compute_child ' , True ) :
2011-06-02 06:55:59 +00:00
child_location_ids = location_obj . search ( cr , uid , [ ( ' location_id ' , ' child_of ' , location_ids ) ] )
2010-05-25 12:03:36 +00:00
location_ids = child_location_ids or location_ids
2011-10-27 15:26:52 +00:00
# this will be a dictionary of the product UoM by product id
2008-09-23 13:24:11 +00:00
product2uom = { }
2012-07-09 13:40:24 +00:00
uom_ids = [ ]
for product in self . read ( cr , uid , ids , [ ' uom_id ' ] , context = context ) :
product2uom [ product [ ' id ' ] ] = product [ ' uom_id ' ] [ 0 ]
uom_ids . append ( product [ ' uom_id ' ] [ 0 ] )
# this will be a dictionary of the UoM resources we need for conversion purposes, by UoM id
uoms_o = { }
for uom in self . pool . get ( ' product.uom ' ) . browse ( cr , uid , uom_ids , context = context ) :
uoms_o [ uom . id ] = uom
2008-09-23 13:24:11 +00:00
results = [ ]
results2 = [ ]
2008-09-23 14:24:03 +00:00
2010-09-21 05:58:33 +00:00
from_date = context . get ( ' from_date ' , False )
to_date = context . get ( ' to_date ' , False )
date_str = False
date_values = False
2010-10-04 10:32:32 +00:00
where = [ tuple ( location_ids ) , tuple ( location_ids ) , tuple ( ids ) , tuple ( states ) ]
2008-09-23 13:24:11 +00:00
if from_date and to_date :
2010-09-21 12:08:55 +00:00
date_str = " date>= %s and date<= %s "
2010-10-04 10:32:32 +00:00
where . append ( tuple ( [ from_date ] ) )
where . append ( tuple ( [ to_date ] ) )
2008-09-23 13:24:11 +00:00
elif from_date :
2010-09-21 12:08:55 +00:00
date_str = " date>= %s "
2010-11-11 12:41:24 +00:00
date_values = [ from_date ]
2008-09-23 13:24:11 +00:00
elif to_date :
2010-09-21 12:08:55 +00:00
date_str = " date<= %s "
2010-09-21 05:58:33 +00:00
date_values = [ to_date ]
2012-06-19 07:40:07 +00:00
if date_values :
where . append ( tuple ( date_values ) )
2008-09-23 14:24:03 +00:00
2011-04-08 13:32:12 +00:00
prodlot_id = context . get ( ' prodlot_id ' , False )
2012-06-18 17:41:53 +00:00
prodlot_clause = ' '
if prodlot_id :
prodlot_clause = ' and prodlot_id = %s '
where + = [ prodlot_id ]
2014-08-07 14:56:27 +00:00
elif ' prodlot_id ' in context and not prodlot_id :
prodlot_clause = ' and prodlot_id is null '
2010-11-11 12:41:24 +00:00
2012-06-19 07:40:07 +00:00
# TODO: perhaps merge in one query.
2008-09-23 13:24:11 +00:00
if ' in ' in what :
2008-09-23 14:24:03 +00:00
# all moves from a location out of the set to a location in the set
2008-09-23 13:24:11 +00:00
cr . execute (
' select sum(product_qty), product_id, product_uom ' \
' from stock_move ' \
2011-04-08 13:32:12 +00:00
' where location_id NOT IN %s ' \
' and location_dest_id IN %s ' \
' and product_id IN %s ' \
' and state IN %s ' + ( date_str and ' and ' + date_str + ' ' or ' ' ) + ' ' \
2012-06-18 17:41:53 +00:00
+ prodlot_clause +
2010-09-21 05:58:33 +00:00
' group by product_id,product_uom ' , tuple ( where ) )
2008-09-23 13:24:11 +00:00
results = cr . fetchall ( )
if ' out ' in what :
2008-09-23 14:24:03 +00:00
# all moves from a location in the set to a location out of the set
2008-09-23 13:24:11 +00:00
cr . execute (
' select sum(product_qty), product_id, product_uom ' \
' from stock_move ' \
2011-04-08 13:32:12 +00:00
' where location_id IN %s ' \
2010-06-16 11:51:39 +00:00
' and location_dest_id NOT IN %s ' \
2011-04-08 13:32:12 +00:00
' and product_id IN %s ' \
' and state in %s ' + ( date_str and ' and ' + date_str + ' ' or ' ' ) + ' ' \
2012-06-18 17:41:53 +00:00
+ prodlot_clause +
2010-09-21 05:58:33 +00:00
' group by product_id,product_uom ' , tuple ( where ) )
2008-09-23 13:24:11 +00:00
results2 = cr . fetchall ( )
2011-10-27 15:26:52 +00:00
# Get the missing UoM resources
2008-09-23 13:24:11 +00:00
uom_obj = self . pool . get ( ' product.uom ' )
2008-12-18 19:39:18 +00:00
uoms = map ( lambda x : x [ 2 ] , results ) + map ( lambda x : x [ 2 ] , results2 )
if context . get ( ' uom ' , False ) :
uoms + = [ context [ ' uom ' ] ]
uoms = filter ( lambda x : x not in uoms_o . keys ( ) , uoms )
if uoms :
uoms = uom_obj . browse ( cr , uid , list ( set ( uoms ) ) , context = context )
2010-11-24 11:54:23 +00:00
for o in uoms :
uoms_o [ o . id ] = o
2011-10-27 15:26:52 +00:00
2010-11-23 11:45:55 +00:00
#TOCHECK: before change uom of product, stock move line are in old uom.
context . update ( { ' raise-exception ' : False } )
2011-10-27 15:26:52 +00:00
# Count the incoming quantities
2008-09-23 13:24:11 +00:00
for amount , prod_id , prod_uom in results :
2008-12-18 19:39:18 +00:00
amount = uom_obj . _compute_qty_obj ( cr , uid , uoms_o [ prod_uom ] , amount ,
2010-11-23 11:45:55 +00:00
uoms_o [ context . get ( ' uom ' , False ) or product2uom [ prod_id ] ] , context = context )
2008-09-23 13:24:11 +00:00
res [ prod_id ] + = amount
2011-10-27 15:26:52 +00:00
# Count the outgoing quantities
2008-09-23 13:24:11 +00:00
for amount , prod_id , prod_uom in results2 :
2008-12-18 19:39:18 +00:00
amount = uom_obj . _compute_qty_obj ( cr , uid , uoms_o [ prod_uom ] , amount ,
2010-11-23 11:45:55 +00:00
uoms_o [ context . get ( ' uom ' , False ) or product2uom [ prod_id ] ] , context = context )
2008-09-23 14:24:03 +00:00
res [ prod_id ] - = amount
return res
2008-09-23 13:24:11 +00:00
2010-07-06 11:56:32 +00:00
def _product_available ( self , cr , uid , ids , field_names = None , arg = False , context = None ) :
2010-05-26 12:59:30 +00:00
""" Finds the incoming and outgoing quantity of product.
@return : Dictionary of values
"""
2008-10-21 16:28:19 +00:00
if not field_names :
2010-05-26 12:59:30 +00:00
field_names = [ ]
2010-07-06 11:56:32 +00:00
if context is None :
context = { }
2008-10-21 16:28:19 +00:00
res = { }
for id in ids :
res [ id ] = { } . fromkeys ( field_names , 0.0 )
for f in field_names :
c = context . copy ( )
2010-05-26 12:59:30 +00:00
if f == ' qty_available ' :
c . update ( { ' states ' : ( ' done ' , ) , ' what ' : ( ' in ' , ' out ' ) } )
if f == ' virtual_available ' :
c . update ( { ' states ' : ( ' confirmed ' , ' waiting ' , ' assigned ' , ' done ' ) , ' what ' : ( ' in ' , ' out ' ) } )
if f == ' incoming_qty ' :
c . update ( { ' states ' : ( ' confirmed ' , ' waiting ' , ' assigned ' ) , ' what ' : ( ' in ' , ) } )
if f == ' outgoing_qty ' :
c . update ( { ' states ' : ( ' confirmed ' , ' waiting ' , ' assigned ' ) , ' what ' : ( ' out ' , ) } )
stock = self . get_product_available ( cr , uid , ids , context = c )
2008-09-07 23:24:39 +00:00
for id in ids :
2008-10-21 16:28:19 +00:00
res [ id ] [ f ] = stock . get ( id , 0.0 )
return res
2008-09-23 14:24:03 +00:00
2008-09-07 23:24:39 +00:00
_columns = {
2012-05-22 07:02:28 +00:00
' reception_count ' : fields . function ( _stock_move_count , string = " Reception " , type = ' integer ' , multi = ' pickings ' ) ,
' delivery_count ' : fields . function ( _stock_move_count , string = " Delivery " , type = ' integer ' , multi = ' pickings ' ) ,
2011-10-28 15:02:09 +00:00
' qty_available ' : fields . function ( _product_available , multi = ' qty_available ' ,
2012-04-25 12:09:08 +00:00
type = ' float ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) ,
2011-10-28 15:02:09 +00:00
string = ' Quantity On Hand ' ,
help = " Current quantity of products. \n "
" In a context with a single Stock Location, this includes "
" goods stored at this Location, or any of its children. \n "
" In a context with a single Warehouse, this includes "
" goods stored in the Stock Location of this Warehouse, or any "
" of its children. \n "
" In a context with a single Shop, this includes goods "
" stored in the Stock Location of the Warehouse of this Shop, "
" or any of its children. \n "
" Otherwise, this includes goods stored in any Stock Location "
2012-10-23 13:02:42 +00:00
" with ' internal ' type. " ) ,
2011-10-28 15:02:09 +00:00
' virtual_available ' : fields . function ( _product_available , multi = ' qty_available ' ,
2012-04-25 12:09:08 +00:00
type = ' float ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) ,
2012-10-29 12:54:26 +00:00
string = ' Forecasted Quantity ' ,
2011-12-22 16:54:22 +00:00
help = " Forecast quantity (computed as Quantity On Hand "
2011-10-28 15:02:09 +00:00
" - Outgoing + Incoming) \n "
" In a context with a single Stock Location, this includes "
2012-10-23 13:02:42 +00:00
" goods stored in this location, or any of its children. \n "
2011-10-28 15:02:09 +00:00
" In a context with a single Warehouse, this includes "
" goods stored in the Stock Location of this Warehouse, or any "
" of its children. \n "
" In a context with a single Shop, this includes goods "
" stored in the Stock Location of the Warehouse of this Shop, "
" or any of its children. \n "
" Otherwise, this includes goods stored in any Stock Location "
2012-10-23 13:02:42 +00:00
" with ' internal ' type. " ) ,
2011-10-28 15:02:09 +00:00
' incoming_qty ' : fields . function ( _product_available , multi = ' qty_available ' ,
2012-04-25 12:09:08 +00:00
type = ' float ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) ,
2011-10-28 15:02:09 +00:00
string = ' Incoming ' ,
help = " Quantity of products that are planned to arrive. \n "
" In a context with a single Stock Location, this includes "
" goods arriving to this Location, or any of its children. \n "
" In a context with a single Warehouse, this includes "
" goods arriving to the Stock Location of this Warehouse, or "
" any of its children. \n "
" In a context with a single Shop, this includes goods "
" arriving to the Stock Location of the Warehouse of this "
" Shop, or any of its children. \n "
" Otherwise, this includes goods arriving to any Stock "
2012-10-23 13:02:42 +00:00
" Location with ' internal ' type. " ) ,
2011-10-28 15:02:09 +00:00
' outgoing_qty ' : fields . function ( _product_available , multi = ' qty_available ' ,
2012-04-25 12:09:08 +00:00
type = ' float ' , digits_compute = dp . get_precision ( ' Product Unit of Measure ' ) ,
2011-10-28 15:02:09 +00:00
string = ' Outgoing ' ,
help = " Quantity of products that are planned to leave. \n "
" In a context with a single Stock Location, this includes "
2012-10-23 13:02:42 +00:00
" goods leaving this Location, or any of its children. \n "
2011-10-28 15:02:09 +00:00
" In a context with a single Warehouse, this includes "
2012-10-23 13:02:42 +00:00
" goods leaving the Stock Location of this Warehouse, or "
2011-10-28 15:02:09 +00:00
" any of its children. \n "
" In a context with a single Shop, this includes goods "
2012-10-23 13:02:42 +00:00
" leaving the Stock Location of the Warehouse of this "
2011-10-28 15:02:09 +00:00
" Shop, or any of its children. \n "
2012-10-23 13:02:42 +00:00
" Otherwise, this includes goods leaving any Stock "
" Location with ' internal ' type. " ) ,
2012-04-24 13:08:05 +00:00
' track_production ' : fields . boolean ( ' Track Manufacturing Lots ' , help = " Forces to specify a Serial Number for all moves containing this product and generated by a Manufacturing Order " ) ,
' track_incoming ' : fields . boolean ( ' Track Incoming Lots ' , help = " Forces to specify a Serial Number for all moves containing this product and coming from a Supplier Location " ) ,
' track_outgoing ' : fields . boolean ( ' Track Outgoing Lots ' , help = " Forces to specify a Serial Number for all moves containing this product and going to a Customer Location " ) ,
2011-07-08 08:52:03 +00:00
' location_id ' : fields . dummy ( string = ' Location ' , relation = ' stock.location ' , type = ' many2one ' ) ,
' warehouse_id ' : fields . dummy ( string = ' Warehouse ' , relation = ' stock.warehouse ' , type = ' many2one ' ) ,
2010-09-15 00:10:44 +00:00
' valuation ' : fields . selection ( [ ( ' manual_periodic ' , ' Periodical (manual) ' ) ,
2010-11-11 12:41:24 +00:00
( ' real_time ' , ' Real Time (automated) ' ) , ] , ' Inventory Valuation ' ,
2010-09-15 00:10:44 +00:00
help = " If real-time valuation is enabled for a product, the system will automatically write journal entries corresponding to stock moves. " \
" The inventory variation account set on the product category will represent the current inventory value, and the stock input and stock output account will hold the counterpart moves for incoming and outgoing products. "
, required = True ) ,
2010-06-10 12:44:52 +00:00
}
_defaults = {
2011-12-22 16:54:22 +00:00
' valuation ' : ' manual_periodic ' ,
2008-09-07 23:24:39 +00:00
}
2010-06-10 12:44:52 +00:00
2009-09-24 10:46:21 +00:00
def fields_view_get ( self , cr , uid , view_id = None , view_type = ' form ' , context = None , toolbar = False , submenu = False ) :
res = super ( product_product , self ) . fields_view_get ( cr , uid , view_id , view_type , context , toolbar = toolbar , submenu = submenu )
2010-07-06 11:56:32 +00:00
if context is None :
2009-12-29 13:05:00 +00:00
context = { }
2008-09-23 13:24:11 +00:00
if ( ' location ' in context ) and context [ ' location ' ] :
location_info = self . pool . get ( ' stock.location ' ) . browse ( cr , uid , context [ ' location ' ] )
fields = res . get ( ' fields ' , { } )
if fields :
2008-09-23 14:24:03 +00:00
if location_info . usage == ' supplier ' :
if fields . get ( ' virtual_available ' ) :
2009-11-13 05:41:16 +00:00
res [ ' fields ' ] [ ' virtual_available ' ] [ ' string ' ] = _ ( ' Future Receptions ' )
2008-09-23 13:24:11 +00:00
if fields . get ( ' qty_available ' ) :
2008-12-08 17:08:40 +00:00
res [ ' fields ' ] [ ' qty_available ' ] [ ' string ' ] = _ ( ' Received Qty ' )
2008-09-23 14:24:03 +00:00
2008-09-23 13:24:11 +00:00
if location_info . usage == ' internal ' :
if fields . get ( ' virtual_available ' ) :
2009-11-13 05:41:16 +00:00
res [ ' fields ' ] [ ' virtual_available ' ] [ ' string ' ] = _ ( ' Future Stock ' )
2008-09-23 14:24:03 +00:00
2008-09-23 13:24:11 +00:00
if location_info . usage == ' customer ' :
if fields . get ( ' virtual_available ' ) :
2009-11-13 05:41:16 +00:00
res [ ' fields ' ] [ ' virtual_available ' ] [ ' string ' ] = _ ( ' Future Deliveries ' )
2008-09-23 13:24:11 +00:00
if fields . get ( ' qty_available ' ) :
2008-12-08 17:08:40 +00:00
res [ ' fields ' ] [ ' qty_available ' ] [ ' string ' ] = _ ( ' Delivered Qty ' )
2008-09-23 14:24:03 +00:00
2008-09-23 13:24:11 +00:00
if location_info . usage == ' inventory ' :
if fields . get ( ' virtual_available ' ) :
2009-11-13 05:41:16 +00:00
res [ ' fields ' ] [ ' virtual_available ' ] [ ' string ' ] = _ ( ' Future P&L ' )
2010-07-06 11:56:32 +00:00
if fields . get ( ' qty_available ' ) :
2010-06-18 07:12:06 +00:00
res [ ' fields ' ] [ ' qty_available ' ] [ ' string ' ] = _ ( ' P&L Qty ' )
2008-09-23 14:24:03 +00:00
2008-09-23 13:24:11 +00:00
if location_info . usage == ' procurement ' :
if fields . get ( ' virtual_available ' ) :
2009-11-13 05:41:16 +00:00
res [ ' fields ' ] [ ' virtual_available ' ] [ ' string ' ] = _ ( ' Future Qty ' )
2008-09-23 13:24:11 +00:00
if fields . get ( ' qty_available ' ) :
2008-12-08 17:08:40 +00:00
res [ ' fields ' ] [ ' qty_available ' ] [ ' string ' ] = _ ( ' Unplanned Qty ' )
2008-09-23 14:24:03 +00:00
2008-09-23 13:24:11 +00:00
if location_info . usage == ' production ' :
if fields . get ( ' virtual_available ' ) :
2009-11-13 05:41:16 +00:00
res [ ' fields ' ] [ ' virtual_available ' ] [ ' string ' ] = _ ( ' Future Productions ' )
2008-09-23 13:24:11 +00:00
if fields . get ( ' qty_available ' ) :
2008-12-08 17:08:40 +00:00
res [ ' fields ' ] [ ' qty_available ' ] [ ' string ' ] = _ ( ' Produced Qty ' )
2008-09-23 13:24:11 +00:00
return res
2008-09-07 23:24:39 +00:00
2010-07-06 11:56:32 +00:00
product_product ( )
2006-12-07 13:41:40 +00:00
2008-09-23 13:24:11 +00:00
class product_template ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = ' product.template '
_inherit = ' product.template '
_columns = {
' property_stock_procurement ' : fields . property (
' stock.location ' ,
type = ' many2one ' ,
relation = ' stock.location ' ,
2010-04-09 07:14:08 +00:00
string = " Procurement Location " ,
2008-07-22 15:11:28 +00:00
view_load = True ,
2009-10-22 13:40:16 +00:00
domain = [ ( ' usage ' , ' like ' , ' procurement ' ) ] ,
2012-10-23 13:02:42 +00:00
help = " This stock location will be used, instead of the default one, as the source location for stock moves generated by procurements. " ) ,
2008-07-22 15:11:28 +00:00
' property_stock_production ' : fields . property (
' stock.location ' ,
type = ' many2one ' ,
relation = ' stock.location ' ,
string = " Production Location " ,
view_load = True ,
2009-10-22 13:40:16 +00:00
domain = [ ( ' usage ' , ' like ' , ' production ' ) ] ,
2012-10-23 13:02:42 +00:00
help = " This stock location will be used, instead of the default one, as the source location for stock moves generated by manufacturing orders. " ) ,
2008-07-22 15:11:28 +00:00
' property_stock_inventory ' : fields . property (
' stock.location ' ,
type = ' many2one ' ,
relation = ' stock.location ' ,
string = " Inventory Location " ,
view_load = True ,
2009-10-22 13:40:16 +00:00
domain = [ ( ' usage ' , ' like ' , ' inventory ' ) ] ,
2012-10-31 10:25:24 +00:00
help = " This stock location will be used, instead of the default one, as the source location for stock moves generated when you do an inventory. " ) ,
2008-07-22 15:11:28 +00:00
' property_stock_account_input ' : fields . property ( ' account.account ' ,
type = ' many2one ' , relation = ' account.account ' ,
2011-07-01 23:41:24 +00:00
string = ' Stock Input Account ' , view_load = True ,
2011-12-01 00:37:55 +00:00
help = " When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless "
" there is a specific valuation account set on the source location. When not set on the product, the one from the product category is used. " ) ,
2008-07-22 15:11:28 +00:00
' property_stock_account_output ' : fields . property ( ' account.account ' ,
type = ' many2one ' , relation = ' account.account ' ,
2011-07-01 23:41:24 +00:00
string = ' Stock Output Account ' , view_load = True ,
2011-12-01 00:37:55 +00:00
help = " When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless "
" there is a specific valuation account set on the destination location. When not set on the product, the one from the product category is used. " ) ,
2012-10-23 13:02:42 +00:00
' sale_delay ' : fields . float ( ' Customer Lead Time ' , help = " The average delay in days between the confirmation of the customer order and the delivery of the finished products. It ' s the time you promise to your customers. " ) ,
2012-10-03 06:48:40 +00:00
' loc_rack ' : fields . char ( ' Rack ' , size = 16 ) ,
' loc_row ' : fields . char ( ' Row ' , size = 16 ) ,
' loc_case ' : fields . char ( ' Case ' , size = 16 ) ,
2008-07-22 15:11:28 +00:00
}
2010-07-06 11:56:32 +00:00
2012-10-03 06:48:40 +00:00
_defaults = {
2012-10-03 11:42:08 +00:00
' sale_delay ' : 7 ,
2012-10-03 06:48:40 +00:00
}
2008-09-23 13:24:11 +00:00
product_template ( )
2006-12-07 13:41:40 +00:00
2007-04-25 14:08:50 +00:00
class product_category ( osv . osv ) :
2010-07-06 11:56:32 +00:00
2008-07-22 15:11:28 +00:00
_inherit = ' product.category '
_columns = {
' property_stock_journal ' : fields . property ( ' account.journal ' ,
relation = ' account.journal ' , type = ' many2one ' ,
2012-11-21 07:17:18 +00:00
string = ' Stock Journal ' , view_load = True ,
2010-09-15 00:10:44 +00:00
help = " When doing real-time inventory valuation, this is the Accounting Journal in which entries will be automatically posted when stock moves are processed. " ) ,
2008-07-22 15:11:28 +00:00
' property_stock_account_input_categ ' : fields . property ( ' account.account ' ,
type = ' many2one ' , relation = ' account.account ' ,
2011-07-01 23:41:24 +00:00
string = ' Stock Input Account ' , view_load = True ,
2011-12-01 00:37:55 +00:00
help = " When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless "
" there is a specific valuation account set on the source location. This is the default value for all products in this category. It "
" can also directly be set on each product " ) ,
2008-07-22 15:11:28 +00:00
' property_stock_account_output_categ ' : fields . property ( ' account.account ' ,
type = ' many2one ' , relation = ' account.account ' ,
2011-07-01 23:41:24 +00:00
string = ' Stock Output Account ' , view_load = True ,
2011-12-01 00:37:55 +00:00
help = " When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless "
" there is a specific valuation account set on the destination location. This is the default value for all products in this category. It "
" can also directly be set on each product " ) ,
2011-10-10 06:19:22 +00:00
' property_stock_valuation_account_id ' : fields . property ( ' account.account ' ,
2010-06-10 12:44:52 +00:00
type = ' many2one ' ,
relation = ' account.account ' ,
2011-09-28 06:21:11 +00:00
string = " Stock Valuation Account " ,
2011-07-05 12:28:57 +00:00
view_load = True ,
2010-09-15 00:10:44 +00:00
help = " When real-time inventory valuation is enabled on a product, this account will hold the current value of the products. " , ) ,
2008-07-22 15:11:28 +00:00
}
2008-07-23 14:41:47 +00:00
2010-07-06 11:56:32 +00:00
product_category ( )
2008-07-23 14:41:47 +00:00
2010-09-21 05:58:33 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: