2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2006-12-07 13:41:40 +00:00
##############################################################################
2009-11-24 12:09:06 +00:00
#
2009-10-14 11:15:34 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2008-06-16 11:00:21 +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
2009-11-24 12:09:06 +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
import time
2006-12-07 13:41:40 +00:00
2014-03-06 16:29:53 +00:00
from openerp import tools
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
import openerp . addons . decimal_precision as dp
2010-03-06 20:52:19 +00:00
2006-12-07 13:41:40 +00:00
class price_type ( osv . osv ) :
2008-07-22 15:11:28 +00:00
"""
The price type is used to points which field in the product form
is a price and in which currency is this price expressed .
When a field is a price , you can use it in pricelists to base
sale and purchase prices based on some fields of the product .
"""
2010-11-19 13:48:01 +00:00
def _price_field_get ( self , cr , uid , context = None ) :
2008-12-13 06:05:19 +00:00
mf = self . pool . get ( ' ir.model.fields ' )
ids = mf . search ( cr , uid , [ ( ' model ' , ' in ' , ( ( ' product.product ' ) , ( ' product.template ' ) ) ) , ( ' ttype ' , ' = ' , ' float ' ) ] , context = context )
2008-12-08 17:08:40 +00:00
res = [ ]
2008-12-13 06:05:19 +00:00
for field in mf . browse ( cr , uid , ids , context = context ) :
res . append ( ( field . name , field . field_description ) )
2008-12-08 17:08:40 +00:00
return res
2014-07-02 16:18:29 +00:00
def _get_field_currency ( self , cr , uid , fname , ctx ) :
ids = self . search ( cr , uid , [ ( ' field ' , ' = ' , fname ) ] , context = ctx )
return self . browse ( cr , uid , ids , context = ctx ) [ 0 ] . currency_id
2008-07-22 15:11:28 +00:00
def _get_currency ( self , cr , uid , ctx ) :
comp = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ) . company_id
if not comp :
comp_id = self . pool . get ( ' res.company ' ) . search ( cr , uid , [ ] ) [ 0 ]
comp = self . pool . get ( ' res.company ' ) . browse ( cr , uid , comp_id )
return comp . currency_id . id
2007-10-23 19:02:01 +00:00
2008-07-22 15:11:28 +00:00
_name = " product.price.type "
2010-05-19 18:32:32 +00:00
_description = " Price Type "
2008-07-22 15:11:28 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
" name " : fields . char ( " Price Name " , required = True , translate = True , help = " Name of this kind of price. " ) ,
2008-07-22 15:11:28 +00:00
" active " : fields . boolean ( " Active " ) ,
2009-01-06 11:17:44 +00:00
" field " : fields . selection ( _price_field_get , " Product Field " , size = 32 , required = True , help = " Associated field in the product form. " ) ,
2008-09-22 06:06:56 +00:00
" currency_id " : fields . many2one ( ' res.currency ' , " Currency " , required = True , help = " The currency the field is expressed in. " ) ,
2008-07-22 15:11:28 +00:00
}
_defaults = {
" active " : lambda * args : True ,
" currency_id " : _get_currency
}
2010-08-13 12:20:05 +00:00
2006-12-07 13:41:40 +00:00
#----------------------------------------------------------
# Price lists
#----------------------------------------------------------
class product_pricelist_type ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = " product.pricelist.type "
_description = " Pricelist Type "
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
' key ' : fields . char ( ' Key ' , required = True , help = " Used in the code to select specific prices based on the context. Keep unchanged. " ) ,
2008-07-22 15:11:28 +00:00
}
2006-12-07 13:41:40 +00:00
class product_pricelist ( osv . osv ) :
2010-11-19 13:48:01 +00:00
def _pricelist_type_get ( self , cr , uid , context = None ) :
2009-10-01 11:32:20 +00:00
pricelist_type_obj = self . pool . get ( ' product.pricelist.type ' )
pricelist_type_ids = pricelist_type_obj . search ( cr , uid , [ ] , order = ' name ' )
pricelist_types = pricelist_type_obj . read ( cr , uid , pricelist_type_ids , [ ' key ' , ' name ' ] , context = context )
2009-11-24 12:09:06 +00:00
2009-10-01 11:32:20 +00:00
res = [ ]
2009-11-24 12:09:06 +00:00
2009-10-01 11:32:20 +00:00
for type in pricelist_types :
res . append ( ( type [ ' key ' ] , type [ ' name ' ] ) )
2009-11-24 12:09:06 +00:00
2009-10-01 11:32:20 +00:00
return res
2010-08-13 12:20:05 +00:00
2008-07-22 15:11:28 +00:00
_name = " product.pricelist "
_description = " Pricelist "
2013-09-06 15:50:47 +00:00
_order = ' name '
2008-07-22 15:11:28 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Pricelist Name ' , required = True , translate = True ) ,
2012-10-23 13:02:42 +00:00
' active ' : fields . boolean ( ' Active ' , help = " If unchecked, it will allow you to hide the pricelist without removing it. " ) ,
2008-07-22 15:11:28 +00:00
' type ' : fields . selection ( _pricelist_type_get , ' Pricelist Type ' , required = True ) ,
2014-07-06 14:44:26 +00:00
' version_id ' : fields . one2many ( ' product.pricelist.version ' , ' pricelist_id ' , ' Pricelist Versions ' , copy = True ) ,
2008-07-22 15:11:28 +00:00
' currency_id ' : fields . many2one ( ' res.currency ' , ' Currency ' , required = True ) ,
2009-12-02 11:20:06 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' ) ,
2008-07-22 15:11:28 +00:00
}
2009-11-24 12:09:06 +00:00
2010-11-19 13:48:01 +00:00
def name_get ( self , cr , uid , ids , context = None ) :
2008-12-26 06:50:18 +00:00
result = [ ]
2009-03-09 13:35:04 +00:00
if not all ( ids ) :
return result
2010-11-19 13:48:01 +00:00
for pl in self . browse ( cr , uid , ids , context = context ) :
2008-12-29 16:33:26 +00:00
name = pl . name + ' ( ' + pl . currency_id . name + ' ) '
2008-12-26 06:50:18 +00:00
result . append ( ( pl . id , name ) )
2008-12-24 15:50:06 +00:00
return result
2009-11-24 12:09:06 +00:00
2013-09-06 15:50:47 +00:00
def name_search ( self , cr , uid , name , args = None , operator = ' ilike ' , context = None , limit = 100 ) :
if name and operator == ' = ' and not args :
# search on the name of the pricelist and its currency, opposite of name_get(),
# Used by the magic context filter in the product search view.
2014-03-17 12:01:26 +00:00
query_args = { ' name ' : name , ' limit ' : limit , ' lang ' : ( context or { } ) . get ( ' lang ' ) or ' en_US ' }
2013-09-06 15:50:47 +00:00
query = """ SELECT p.id
2014-03-17 12:01:26 +00:00
FROM ( (
SELECT pr . id , pr . name
FROM product_pricelist pr JOIN
res_currency cur ON
( pr . currency_id = cur . id )
WHERE pr . name | | ' ( ' | | cur . name | | ' ) ' = % ( name ) s
)
UNION (
SELECT tr . res_id as id , tr . value as name
FROM ir_translation tr JOIN
product_pricelist pr ON (
pr . id = tr . res_id AND
tr . type = ' model ' AND
tr . name = ' product.pricelist,name ' AND
tr . lang = % ( lang ) s
) JOIN
res_currency cur ON
( pr . currency_id = cur . id )
WHERE tr . value | | ' ( ' | | cur . name | | ' ) ' = % ( name ) s
)
) p
2013-09-06 15:50:47 +00:00
ORDER BY p . name """
if limit :
query + = " LIMIT %(limit)s "
cr . execute ( query , query_args )
ids = [ r [ 0 ] for r in cr . fetchall ( ) ]
# regular search() to apply ACLs - may limit results below limit in some cases
ids = self . search ( cr , uid , [ ( ' id ' , ' in ' , ids ) ] , limit = limit , context = context )
if ids :
return self . name_get ( cr , uid , ids , context )
return super ( product_pricelist , self ) . name_search (
cr , uid , name , args , operator = operator , context = context , limit = limit )
2008-12-24 15:50:06 +00:00
2008-07-22 15:11:28 +00:00
def _get_currency ( self , cr , uid , ctx ) :
2008-12-29 14:55:49 +00:00
comp = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid ) . company_id
2008-07-22 15:11:28 +00:00
if not comp :
comp_id = self . pool . get ( ' res.company ' ) . search ( cr , uid , [ ] ) [ 0 ]
comp = self . pool . get ( ' res.company ' ) . browse ( cr , uid , comp_id )
return comp . currency_id . id
2007-10-23 19:02:01 +00:00
2008-07-22 15:11:28 +00:00
_defaults = {
' active ' : lambda * a : 1 ,
" currency_id " : _get_currency
}
2006-12-07 13:41:40 +00:00
2014-07-06 14:44:26 +00:00
def price_get_multi ( self , cr , uid , ids , products_by_qty_by_partner , context = None ) :
2014-10-15 12:51:22 +00:00
return dict ( ( key , price [ 0 ] ) for key , price in self . price_rule_get_multi ( cr , uid , ids , products_by_qty_by_partner , context = context ) . items ( ) )
def price_rule_get_multi ( self , cr , uid , ids , products_by_qty_by_partner , context = None ) :
2010-09-29 09:57:42 +00:00
""" multi products ' price_get ' .
2014-07-06 14:44:26 +00:00
@param ids :
2010-10-28 11:36:41 +00:00
@param products_by_qty :
@param partner :
2010-09-29 09:57:42 +00:00
@param context : {
' date ' : Date of the pricelist ( % Y - % m - % d ) , }
@return : a dict of dict with product_id as key and a dict ' price by pricelist ' as value
"""
2014-07-06 14:44:26 +00:00
if not ids :
ids = self . pool . get ( ' product.pricelist ' ) . search ( cr , uid , [ ] , context = context )
2013-12-06 22:18:09 +00:00
results = { }
2014-07-06 14:44:26 +00:00
for pricelist in self . browse ( cr , uid , ids , context = context ) :
2014-10-15 12:51:22 +00:00
subres = self . _price_rule_get_multi ( cr , uid , pricelist , products_by_qty_by_partner , context = context )
2013-12-06 22:18:09 +00:00
for product_id , price in subres . items ( ) :
results . setdefault ( product_id , { } )
results [ product_id ] [ pricelist . id ] = price
return results
2010-09-29 09:57:42 +00:00
2013-12-06 22:18:09 +00:00
def _price_get_multi ( self , cr , uid , pricelist , products_by_qty_by_partner , context = None ) :
2014-10-15 12:51:22 +00:00
return dict ( ( key , price [ 0 ] ) for key , price in self . _price_rule_get_multi ( cr , uid , pricelist , products_by_qty_by_partner , context = context ) . items ( ) )
def _price_rule_get_multi ( self , cr , uid , pricelist , products_by_qty_by_partner , context = None ) :
2013-12-06 22:18:09 +00:00
context = context or { }
2013-05-17 06:57:44 +00:00
date = context . get ( ' date ' ) or time . strftime ( ' % Y- % m- %d ' )
2010-09-29 09:57:42 +00:00
2013-12-06 22:18:09 +00:00
products = map ( lambda x : x [ 0 ] , products_by_qty_by_partner )
2010-09-29 09:57:42 +00:00
currency_obj = self . pool . get ( ' res.currency ' )
2014-05-27 07:42:52 +00:00
product_obj = self . pool . get ( ' product.template ' )
2010-09-29 09:57:42 +00:00
product_uom_obj = self . pool . get ( ' product.uom ' )
price_type_obj = self . pool . get ( ' product.price.type ' )
2014-05-27 07:42:52 +00:00
if not products :
return { }
2013-12-06 22:18:09 +00:00
version = False
for v in pricelist . version_id :
if ( ( v . date_start is False ) or ( v . date_start < = date ) ) and ( ( v . date_end is False ) or ( v . date_end > = date ) ) :
version = v
break
2014-03-05 11:03:14 +00:00
if not version :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " At least one pricelist has no active version ! \n Please create or activate one. " ) )
2013-12-06 22:18:09 +00:00
categ_ids = { }
for p in products :
categ = p . categ_id
while categ :
categ_ids [ categ . id ] = True
categ = categ . parent_id
categ_ids = categ_ids . keys ( )
2014-05-27 07:42:52 +00:00
is_product_template = products [ 0 ] . _name == " product.template "
if is_product_template :
prod_tmpl_ids = [ tmpl . id for tmpl in products ]
prod_ids = [ product . id for product in tmpl . product_variant_ids for tmpl in products ]
else :
prod_ids = [ product . id for product in products ]
prod_tmpl_ids = [ product . product_tmpl_id . id for product in products ]
2013-12-06 22:18:09 +00:00
# Load all rules
cr . execute (
' SELECT i.id '
' FROM product_pricelist_item AS i '
' WHERE (product_tmpl_id IS NULL OR product_tmpl_id = any( %s )) '
' AND (product_id IS NULL OR (product_id = any( %s ))) '
' AND ((categ_id IS NULL) OR (categ_id = any( %s ))) '
' AND (price_version_id = %s ) '
' ORDER BY sequence, min_quantity desc ' ,
( prod_tmpl_ids , prod_ids , categ_ids , version . id ) )
item_ids = [ x [ 0 ] for x in cr . fetchall ( ) ]
items = self . pool . get ( ' product.pricelist.item ' ) . browse ( cr , uid , item_ids , context = context )
price_types = { }
2010-09-29 09:57:42 +00:00
results = { }
2013-12-06 22:18:09 +00:00
for product , qty , partner in products_by_qty_by_partner :
uom_price_already_computed = False
results [ product . id ] = 0.0
price = False
2014-10-15 12:51:22 +00:00
rule_id = False
2013-12-06 22:18:09 +00:00
for rule in items :
if rule . min_quantity and qty < rule . min_quantity :
continue
2014-05-27 07:42:52 +00:00
if is_product_template :
2014-07-06 14:44:26 +00:00
if rule . product_tmpl_id and product . id != rule . product_tmpl_id . id :
2014-05-27 07:42:52 +00:00
continue
if rule . product_id :
continue
else :
2014-07-06 14:44:26 +00:00
if rule . product_tmpl_id and product . product_tmpl_id . id != rule . product_tmpl_id . id :
2014-05-27 07:42:52 +00:00
continue
2014-07-06 14:44:26 +00:00
if rule . product_id and product . id != rule . product_id . id :
2014-05-27 07:42:52 +00:00
continue
2013-12-06 22:18:09 +00:00
if rule . categ_id :
cat = product . categ_id
while cat :
if cat . id == rule . categ_id . id :
2010-09-29 09:57:42 +00:00
break
2013-12-06 22:18:09 +00:00
cat = cat . parent_id
if not cat :
continue
if rule . base == - 1 :
if rule . base_pricelist_id :
price_tmp = self . _price_get_multi ( cr , uid ,
rule . base_pricelist_id , [ ( product ,
qty , False ) ] , context = context ) [ product . id ]
ptype_src = rule . base_pricelist_id . currency_id . id
uom_price_already_computed = True
price = currency_obj . compute ( cr , uid ,
ptype_src , pricelist . currency_id . id ,
price_tmp , round = False ,
context = context )
elif rule . base == - 2 :
for seller in product . seller_ids :
2014-07-06 14:44:26 +00:00
if ( not partner ) or ( seller . name . id != partner ) :
2013-12-06 22:18:09 +00:00
continue
2014-02-12 17:51:41 +00:00
qty_in_seller_uom = qty
from_uom = context . get ( ' uom ' ) or product . uom_id . id
2013-12-06 22:18:09 +00:00
seller_uom = seller . product_uom and seller . product_uom . id or False
2014-02-12 17:51:41 +00:00
if seller_uom and from_uom and from_uom != seller_uom :
qty_in_seller_uom = product_uom_obj . _compute_qty ( cr , uid , from_uom , qty , to_uom_id = seller_uom )
2010-09-29 09:57:42 +00:00
else :
2013-12-06 22:18:09 +00:00
uom_price_already_computed = True
for line in seller . pricelist_ids :
2014-02-12 17:51:41 +00:00
if line . min_quantity < = qty_in_seller_uom :
2013-12-06 22:18:09 +00:00
price = line . price
2010-09-29 09:57:42 +00:00
else :
2013-12-06 22:18:09 +00:00
if rule . base not in price_types :
price_types [ rule . base ] = price_type_obj . browse ( cr , uid , int ( rule . base ) )
price_type = price_types [ rule . base ]
uom_price_already_computed = True
price = currency_obj . compute ( cr , uid ,
price_type . currency_id . id , pricelist . currency_id . id ,
product_obj . _price_get ( cr , uid , [ product ] ,
price_type . field , context = context ) [ product . id ] , round = False , context = context )
if price is not False :
price_limit = price
price = price * ( 1.0 + ( rule . price_discount or 0.0 ) )
2014-03-10 14:36:00 +00:00
if rule . price_round :
price = tools . float_round ( price , precision_rounding = rule . price_round )
2013-12-06 22:18:09 +00:00
price + = ( rule . price_surcharge or 0.0 )
if rule . price_min_margin :
price = max ( price , price_limit + rule . price_min_margin )
if rule . price_max_margin :
price = min ( price , price_limit + rule . price_max_margin )
2014-10-15 12:51:22 +00:00
rule_id = rule . id
2013-12-06 22:18:09 +00:00
break
if price :
if ' uom ' in context and not uom_price_already_computed :
uom = product . uos_id or product . uom_id
price = product_uom_obj . _compute_price ( cr , uid , uom . id , price , context [ ' uom ' ] )
2014-10-15 12:51:22 +00:00
results [ product . id ] = ( price , rule_id )
2010-09-27 14:21:50 +00:00
return results
2008-07-22 15:11:28 +00:00
def price_get ( self , cr , uid , ids , prod_id , qty , partner = None , context = None ) :
2014-10-15 12:51:22 +00:00
return dict ( ( key , price [ 0 ] ) for key , price in self . price_rule_get ( cr , uid , ids , prod_id , qty , partner = partner , context = context ) . items ( ) )
def price_rule_get ( self , cr , uid , ids , prod_id , qty , partner = None , context = None ) :
2013-12-06 22:18:09 +00:00
product = self . pool . get ( ' product.product ' ) . browse ( cr , uid , prod_id , context = context )
2014-10-15 12:51:22 +00:00
res_multi = self . price_rule_get_multi ( cr , uid , ids , products_by_qty_by_partner = [ ( product , qty , partner ) ] , context = context )
2010-09-29 09:57:42 +00:00
res = res_multi [ prod_id ]
return res
2006-12-07 13:41:40 +00:00
class product_pricelist_version ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = " product.pricelist.version "
_description = " Pricelist Version "
_columns = {
' pricelist_id ' : fields . many2one ( ' product.pricelist ' , ' Price List ' ,
2010-02-04 07:12:40 +00:00
required = True , select = True , ondelete = ' cascade ' ) ,
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
2009-03-15 17:52:31 +00:00
' active ' : fields . boolean ( ' Active ' ,
help = " When a version is duplicated it is set to non active, so that the " \
" dates do not overlaps with original version. You should change the dates " \
2014-07-06 14:44:26 +00:00
" and reactivate the pricelist " , copy = False ) ,
2008-07-22 15:11:28 +00:00
' items_id ' : fields . one2many ( ' product.pricelist.item ' ,
2014-07-06 14:44:26 +00:00
' price_version_id ' , ' Price List Items ' , required = True , copy = True ) ,
2012-10-23 13:02:42 +00:00
' date_start ' : fields . date ( ' Start Date ' , help = " First valid date for the version. " ) ,
' date_end ' : fields . date ( ' End Date ' , help = " Last valid date for the version. " ) ,
2009-12-23 14:11:38 +00:00
' company_id ' : fields . related ( ' pricelist_id ' , ' company_id ' , type = ' many2one ' ,
readonly = True , relation = ' res.company ' , string = ' Company ' , store = True )
2008-07-22 15:11:28 +00:00
}
_defaults = {
' active ' : lambda * a : 1 ,
}
2007-10-10 05:44:59 +00:00
2010-11-19 13:48:01 +00:00
def _check_date ( self , cursor , user , ids , context = None ) :
for pricelist_version in self . browse ( cursor , user , ids , context = context ) :
2008-07-22 15:11:28 +00:00
if not pricelist_version . active :
continue
2009-03-15 17:52:31 +00:00
where = [ ]
if pricelist_version . date_start :
where . append ( " ((date_end>= ' %s ' ) or (date_end is null)) " % ( pricelist_version . date_start , ) )
if pricelist_version . date_end :
where . append ( " ((date_start<= ' %s ' ) or (date_start is null)) " % ( pricelist_version . date_end , ) )
2009-04-09 10:02:19 +00:00
2008-07-22 15:11:28 +00:00
cursor . execute ( ' SELECT id ' \
' FROM product_pricelist_version ' \
2009-03-15 17:52:31 +00:00
' WHERE ' + ' and ' . join ( where ) + ( where and ' and ' or ' ' ) +
' pricelist_id = %s ' \
2008-07-22 15:11:28 +00:00
' AND active ' \
2009-03-15 17:52:31 +00:00
' AND id <> %s ' , (
2008-07-22 15:11:28 +00:00
pricelist_version . pricelist_id . id ,
pricelist_version . id ) )
if cursor . fetchall ( ) :
return False
return True
2007-10-10 05:44:59 +00:00
2008-07-22 15:11:28 +00:00
_constraints = [
2009-04-09 10:02:19 +00:00
( _check_date , ' You cannot have 2 pricelist versions that overlap! ' ,
2008-07-22 15:11:28 +00:00
[ ' date_start ' , ' date_end ' ] )
]
2007-10-10 05:44:59 +00:00
2006-12-07 13:41:40 +00:00
class product_pricelist_item ( osv . osv ) :
2010-11-19 13:48:01 +00:00
def _price_field_get ( self , cr , uid , context = None ) :
2008-12-13 06:05:19 +00:00
pt = self . pool . get ( ' product.price.type ' )
ids = pt . search ( cr , uid , [ ] , context = context )
2008-12-08 17:08:40 +00:00
result = [ ]
2008-12-13 06:05:19 +00:00
for line in pt . browse ( cr , uid , ids , context = context ) :
result . append ( ( line . id , line . name ) )
2008-12-08 17:08:40 +00:00
result . append ( ( - 1 , _ ( ' Other Pricelist ' ) ) )
2013-03-21 14:34:59 +00:00
result . append ( ( - 2 , _ ( ' Supplier Prices on the product form ' ) ) )
2008-07-22 15:11:28 +00:00
return result
2006-12-07 13:41:40 +00:00
2013-07-12 07:36:54 +00:00
# Added default function to fetch the Price type Based on Pricelist type.
def _get_default_base ( self , cr , uid , fields , context = None ) :
product_price_type_obj = self . pool . get ( ' product.price.type ' )
2013-05-29 13:57:34 +00:00
if fields . get ( ' type ' ) == ' purchase ' :
2013-07-12 07:36:54 +00:00
product_price_type_ids = product_price_type_obj . search ( cr , uid , [ ( ' field ' , ' = ' , ' standard_price ' ) ] , context = context )
elif fields . get ( ' type ' ) == ' sale ' :
product_price_type_ids = product_price_type_obj . search ( cr , uid , [ ( ' field ' , ' = ' , ' list_price ' ) ] , context = context )
2013-05-29 13:57:34 +00:00
else :
2013-07-12 07:36:54 +00:00
return - 1
if not product_price_type_ids :
return False
else :
pricetype = product_price_type_obj . browse ( cr , uid , product_price_type_ids , context = context ) [ 0 ]
return pricetype . id
2013-05-29 13:57:34 +00:00
2008-07-22 15:11:28 +00:00
_name = " product.pricelist.item "
_description = " Pricelist item "
_order = " sequence, min_quantity desc "
_defaults = {
2013-07-12 07:36:54 +00:00
' base ' : _get_default_base ,
2008-07-22 15:11:28 +00:00
' min_quantity ' : lambda * a : 0 ,
' sequence ' : lambda * a : 5 ,
' price_discount ' : lambda * a : 0 ,
}
2009-11-24 12:09:06 +00:00
2010-11-19 13:48:01 +00:00
def _check_recursion ( self , cr , uid , ids , context = None ) :
for obj_list in self . browse ( cr , uid , ids , context = context ) :
2009-11-04 09:56:30 +00:00
if obj_list . base == - 1 :
main_pricelist = obj_list . price_version_id . pricelist_id . id
other_pricelist = obj_list . base_pricelist_id . id
if main_pricelist == other_pricelist :
2009-11-24 12:09:06 +00:00
return False
2009-11-04 09:56:30 +00:00
return True
2009-11-24 12:09:06 +00:00
2012-09-25 11:48:22 +00:00
def _check_margin ( self , cr , uid , ids , context = None ) :
for item in self . browse ( cr , uid , ids , context = context ) :
2012-09-26 08:22:50 +00:00
if item . price_max_margin and item . price_min_margin and ( item . price_min_margin > item . price_max_margin ) :
return False
2012-09-25 11:48:22 +00:00
return True
2008-07-22 15:11:28 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Rule Name ' , help = " Explicit rule name for this pricelist line. " ) ,
2010-02-04 07:12:40 +00:00
' price_version_id ' : fields . many2one ( ' product.pricelist.version ' , ' Price List Version ' , required = True , select = True , ondelete = ' cascade ' ) ,
2012-10-23 13:02:42 +00:00
' product_tmpl_id ' : fields . many2one ( ' product.template ' , ' Product Template ' , ondelete = ' cascade ' , help = " Specify a template if this rule only applies to one product template. Keep empty otherwise. " ) ,
' product_id ' : fields . many2one ( ' product.product ' , ' Product ' , ondelete = ' cascade ' , help = " Specify a product if this rule only applies to one product. Keep empty otherwise. " ) ,
' categ_id ' : fields . many2one ( ' product.category ' , ' Product Category ' , ondelete = ' cascade ' , help = " Specify a product category if this rule only applies to products belonging to this category or its children categories. Keep empty otherwise. " ) ,
2006-12-07 13:41:40 +00:00
2014-09-09 05:49:43 +00:00
' min_quantity ' : fields . integer ( ' Min. Quantity ' , required = True , help = " For the rule to apply, bought/sold quantity must be greater than or equal to minimum quantity specified in this field. " ) ,
2010-12-21 11:29:25 +00:00
' sequence ' : fields . integer ( ' Sequence ' , required = True , help = " Gives the order in which the pricelist items will be checked. The evaluation gives highest priority to lowest sequence and stops as soon as a matching item is found. " ) ,
2012-10-23 13:02:42 +00:00
' base ' : fields . selection ( _price_field_get , ' Based on ' , required = True , size = - 1 , help = " Base price for computation. " ) ,
2012-10-09 06:38:14 +00:00
' base_pricelist_id ' : fields . many2one ( ' product.pricelist ' , ' Other Pricelist ' ) ,
2006-12-07 13:41:40 +00:00
2008-07-22 15:11:28 +00:00
' price_surcharge ' : fields . float ( ' Price Surcharge ' ,
2012-09-25 10:18:50 +00:00
digits_compute = dp . get_precision ( ' Product Price ' ) , help = ' Specify the fixed amount to add or substract(if negative) to the amount calculated with the discount. ' ) ,
2008-07-22 15:11:28 +00:00
' price_discount ' : fields . float ( ' Price Discount ' , digits = ( 16 , 4 ) ) ,
' price_round ' : fields . float ( ' Price Rounding ' ,
2012-07-11 13:06:15 +00:00
digits_compute = dp . get_precision ( ' Product Price ' ) ,
2008-09-22 05:56:30 +00:00
help = " Sets the price so that it is a multiple of this value. \n " \
" Rounding is applied after the discount and before the surcharge. \n " \
2009-01-27 11:15:46 +00:00
" To have prices that end in 9.99, set rounding 10, surcharge -0.01 " \
2008-09-22 05:56:30 +00:00
) ,
2009-01-27 11:15:46 +00:00
' price_min_margin ' : fields . float ( ' Min. Price Margin ' ,
2012-09-19 11:05:40 +00:00
digits_compute = dp . get_precision ( ' Product Price ' ) , help = ' Specify the minimum amount of margin over the base price. ' ) ,
2009-01-27 11:15:46 +00:00
' price_max_margin ' : fields . float ( ' Max. Price Margin ' ,
2012-09-19 11:05:40 +00:00
digits_compute = dp . get_precision ( ' Product Price ' ) , help = ' Specify the maximum amount of margin over the base price. ' ) ,
2009-12-23 14:11:38 +00:00
' company_id ' : fields . related ( ' price_version_id ' , ' company_id ' , type = ' many2one ' ,
readonly = True , relation = ' res.company ' , string = ' Company ' , store = True )
2008-07-22 15:11:28 +00:00
}
2009-11-24 12:09:06 +00:00
2009-11-04 09:56:30 +00:00
_constraints = [
2012-09-26 08:22:50 +00:00
( _check_recursion , ' Error! You cannot assign the Main Pricelist as Other Pricelist in PriceList Item! ' , [ ' base_pricelist_id ' ] ) ,
( _check_margin , ' Error! The minimum margin should be lower than the maximum margin. ' , [ ' price_min_margin ' , ' price_max_margin ' ] )
2009-11-04 09:56:30 +00:00
]
2009-11-24 12:09:06 +00:00
2010-11-19 13:48:01 +00:00
def product_id_change ( self , cr , uid , ids , product_id , context = None ) :
2008-07-22 15:11:28 +00:00
if not product_id :
return { }
prod = self . pool . get ( ' product.product ' ) . read ( cr , uid , [ product_id ] , [ ' code ' , ' name ' ] )
if prod [ 0 ] [ ' code ' ] :
return { ' value ' : { ' name ' : prod [ 0 ] [ ' code ' ] } }
return { }
2006-12-07 13:41:40 +00:00
2008-07-23 14:41:47 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: