Hello.  I'm trying to mod an open source app called TinyERP and inherit
from a parent object, and in essence change how _column is defined.  I
found sample code of:

class custom_product(osv.osv):
  __inherits__ = "product.product"
  __name__ = "product.product"
 _columns  = {
    'color' : fields.many2one('color','Color'),
    'size': fields.many2one('size','Size'),
 }
custom_product()

This doesn't work.  It does seem to override it, however, it seems to
replace the function.  How can I essentially redefine the _columns var?

Thanks,  Graeme

The main class looks like this:
from osv import fields
from osv import osv
from osv import orm


#----------------------------------------------------------
# UOM
#----------------------------------------------------------

class product_uom_categ(osv.osv):
        _name = 'product.uom.categ'
        _description = 'Product uom categ'
        _columns = {
                'name': fields.char('Name', size=64, required=True),
        }
product_uom_categ()

class product_uom(osv.osv):
        _name = 'product.uom'
        _description = 'Product Unit of Measure'
        _columns = {
                'name': fields.char('Name', size=64, required=True),
                'category_id': fields.many2one('product.uom.categ', 'UOM 
Category',
required=True, ondelete='cascade'),
                'factor': fields.float('Factor', required=True),
                'rounding': fields.integer('Rounding Precision', required=True),
                'active': fields.boolean('Active')
        }
        _defaults = {
                'factor': lambda x,y,z: 1.0,
                'active': lambda x,y,z: 1,
                'rounding': lambda x,y,z: 2,
        }
        def _compute_qty(self, cr, uid, uom_id, qty):
                if not uom_id or not qty:
                        return qty
                f = self.read(cr, uid, [uom_id], ['factor','rounding'])[0]
                return int(qty / f['factor'])

        def _compute_price(self, cr, uid, uom_id, qty):
                if not uom_id or not qty:
                        return qty
                f = self.read(cr, uid, [uom_id], ['factor','rounding'])[0]
                return round(qty * f['factor'], f['rounding'])

product_uom()

#----------------------------------------------------------
# Categories
#----------------------------------------------------------
class product_category(osv.osv):
        _name = "product.category"
        _description = "Product Category"
        _columns = {
                'name': fields.char('Name', size=64, required=True),
                'parent_id': fields.many2one('product.category','Parent 
Category'),
                'child_id': fields.one2many('product.category', 'parent_id',
string='Childs Categories')
        }
        def child_get(self, cr, uid, ids):
                return [ids]
product_category()

#----------------------------------------------------------
# Products
#----------------------------------------------------------
class product_template(osv.osv):

        _name = "product.template"
        _description = "Product Template"
        _columns = {
                'name': fields.char('Name', size=64, required=True, 
translate=True),
                'description': fields.text('Description', translate=True),
                'description_purchase': fields.text('Purchase Description',
translate=True),
                'description_sale': fields.text('Sale Description', 
translate=True),
                'name_ids': fields.one2many('product.template.name', 
'template_id',
'Names for Partners'),
                'type': fields.selection([('product','Stockable
Product'),('service','Service')], 'Product Type', required=True),
                'supply_method':
fields.selection([('produce','Produce'),('buy','Buy')], 'Supply
method', required=True),
                'seller_id': fields.many2one('res.partner', 'Default Supplier'),
                'seller_delay': fields.float('Supplier lead time'),
                'sale_delay': fields.float('Procurement lead time'),
                'seller_ids': fields.many2many('res.partner',
'product_product_supplier', 'product_id','partner_id','Alternative
Suppliers'),
                'manufacturer' : fields.char('Manufacturer', size=64),
                'manufacturer_pname' : fields.char('Manufacturer product name',
size=64),
                'manufacturer_pref' : fields.char('Manufacturer product code',
size=64),
                'procure_method': fields.selection([('make_to_stock','Make to
Stock'),('make_to_order','Make to Order')], 'Procure Method',
required=True),
                'rental': fields.boolean('Rentable product'),
                'categ_id': fields.many2one('product.category','Category',
required=True),
                'list_price': fields.float('List Price'),
                'volume': fields.float('Volume'),
                'weight': fields.float('Weight'),
                'cost_method': fields.selection([('standard','Standard Price'),
('pmp','PMP (Not implemented!)')], 'Costing Method', required=True),
                'standard_price': fields.float('Standard Price', required=True),
                'limit_price': fields.float('Limit Price'),
                'warranty': fields.float('Warranty (months)'),
                'sale_ok': fields.boolean('Can be sold'),
                'purchase_ok': fields.boolean('Can be Purchased'),
                'taxes_id': fields.many2many('account.tax', 'product_taxes_rel',
'prod_id', 'tax_id', 'Product Taxes'),
                'uom_id': fields.many2one('product.uom', 'Default UOM',
required=True),
                'uom_po_id': fields.many2one('product.uom', 'Purchase UOM',
required=True),
                'state': fields.selection([('draft', 'In
Development'),('sellable','Sellable'),('end','End of
lifecycle'),('obsolete','Obsolete')], 'State'),
        }
        _defaults = {
                'type': lambda x,y,z: 'product',
                'list_price': lambda x,y,z: 1,
                'cost_method': lambda x,y,z: 'standard',
                'supply_method': lambda x,y,z: 'buy',
                'standard_price': lambda x,y,z: 1,
                'limit_price': lambda x,y,z: 1,
                'sale_ok': lambda x,y,z: 1,
                'sale_delay': lambda x,y,z: 7,
                'purchase_ok': lambda x,y,z: 1,
                'procure_method': lambda x,y,z: 'make_to_stock',
                'specific_bom': lambda x,y,z: False,
                'specific_routing': lambda x,y,z: False,
        }
        # TODO: redefine name_get & name_search for product.template.name
        def name_get(self, cr, user, ids, context={}):
                if 'partner_id' in context:
                        pass
                return orm.orm.name_get(self, cr, user, ids, context)

product_template()

class product_template_name(osv.osv):
        _name = "product.template.name"
        _description = "Product Template"
        _columns = {
                'name': fields.char('Product Name', size=64, required=True),
                'code': fields.char('Product Code', size=32),
                'partner_id': fields.many2one('res.partner', 'Partner',
ondelete='cascade'),
                'template_id': fields.many2one('product.template', 'Product
Template', ondelete='cascade'),
        }
product_template_name()

class product_product(osv.osv):
        def _product_price(self, cr, uid, ids, name, arg, context={}):
                res = {}
                quantity = context.get('quantity', 1)
                pricelist = context.get('pricelist', False)
                if pricelist:
                        for id in ids:
                                price =
self.pool.get('product.pricelist').price_get(cr,uid,[pricelist], id,
quantity, 'list')[pricelist]
                                res[id] = price
                for id in ids:
                        res.setdefault(id, 0.0)
                if 'uom' in context:
                        for id in ids:
                                res[id] = 
self.pool.get('product.uom')._compute_price(cr, uid,
context['uom'], res[id])
                return res

        def _product_virtual_available(self, cr, uid, ids, name, arg,
context={}):
                res = {}
                if ('shop' in context) and context['shop']:
                        cr.execute('select warehouse_id from sale_shop where 
id=%d',
(int(context['shop']),))
                        res = cr.fetchone()
                        if res:
                                context['warehouse'] = res[0]
                if context.get('warehouse',False):
                        cr.execute('select lot_stock_id from stock_warehouse 
where id=%d',
(int(context['warehouse']),))
                        res = cr.fetchone()
                        context['location'] = res[0]
                if context.get('location',False):
                        res = 
self.pool.get('stock.location')._product_virtual_get(cr, uid,
context['location'], ids)
                for id in ids:
                        res.setdefault(id, 0)
                if 'uom' in context:
                        for id in ids:
                                res[id] = 
self.pool.get('product.uom')._compute_qty(cr, uid,
context['uom'], res[id])
                return res

        def _product_qty_available(self, cr, uid, ids, name, arg, context={}):
                res = {}
                if 'shop' in context:
                        cr.execute('select warehouse_id from sale_shop where 
id=%d',
(int(context['shop']),))
                        res = cr.fetchone() or {}
                        if res:
                                context['warehouse'] = res[0]
                if context.get('warehouse',False):
                        cr.execute('select lot_stock_id from stock_warehouse 
where id=%d',
(int(context['warehouse']),))
                        res = cr.fetchone() or {}
                        if res:
                                context['location'] = res[0]

                if context.get('location',False):
                        res = self.pool.get('stock.location')._product_get(cr, 
uid,
context['location'], ids) or {}
                for id in ids:
                        res.setdefault(id, 0)
                if 'uom' in context:
                        for id in ids:
                                res[id] = 
self.pool.get('product.uom')._compute_qty(cr, uid,
context['uom'], res[id])
                return res

        def _product_lst_price(self, cr, uid, ids, name, arg, context={}):
                res = {}
                for p in self.browse(cr, uid, ids):
                        res[p.id] = p.list_price
                for id in ids:
                        res.setdefault(id, 0)
                if 'uom' in context:
                        for id in ids:
                                res[id] = 
self.pool.get('product.uom')._compute_price(cr, uid,
context['uom'], res[id])
                return res

        def _get_partner_code_name(self, cr, uid, ids, product_id,
partner_id):
                product = self.browse(cr, uid, [product_id])[0]
                for name in product.name_ids:
                        if name.partner_id.id == partner_id:
                                return {'code' : name.code, 'name' : name.name}
                return {'code' : product.default_code, 'name' : product.name}

        def _product_code(self, cr, uid, ids, name, arg, context={}):
                res = {}
                for p in self.browse(cr, uid, ids):
                        res[p.id] = self._get_partner_code_name(cr, uid, [], 
p.id,
context.get('partner_id', None))['code']
                return res

        def _product_partner_ref(self, cr, uid, ids, name, arg, context={}):
                res = {}
                for p in self.browse(cr, uid, ids):
                        res[p.id] = self._get_partner_code_name(cr, uid, [], 
p.id,
context.get('partner_id', None))['name']
                return res

        _defaults = {
                'active': lambda x,y,z: 1
        }
        _name = "product.product"
        _description = "Product"
        _table = "product_product"
        _inherits = {'product.template': 'product_tmpl_id'}
        _columns = {
                'qty_available': fields.function(_product_qty_available, 
method=True,
type='integer', string='Real Stock'),
                'virtual_available': fields.function(_product_virtual_available,
method=True, type='integer', string='Virtual Stock'),
                'price': fields.function(_product_price, method=True, 
type='float',
string='Customer Price'),
                'lst_price' : fields.function(_product_lst_price, method=True,
type='float', string='List price'),
                'code': fields.function(_product_code, method=True, type='char',
string='Code'),
                'partner_ref' : fields.function(_product_partner_ref, 
method=True,
type='char', string='Customer ref'),
                'default_code' : fields.char('Code', size=64),
                'active': fields.boolean('Active'),
                'variants': fields.char('Variants', size=64),
                'list_price_margin': fields.float('List Price Margin'),
                'list_price_extra': fields.float('List Price Extra'),
                'standard_price_margin': fields.float('Standard Price Margin'),
                'standard_price_extra': fields.float('Standard Price Extra'),
                'limit_price_margin': fields.float('Limit Price Margin'),
                'limit_price_extra': fields.float('Limit Price Extra'),
                'product_tmpl_id': fields.many2one('product.template', 'Product
Template', required=True),
        }

        def on_order(self, cr, uid, ids, orderline, quantity):
                pass

        def name_get(self, cr, user, ids, context={}):
                if not len(ids):
                        return []
                def _name_get(d):
                        name = self._product_partner_ref(cr, user, [d['id']], 
'', '',
context)[d['id']]
                        code = self._product_code(cr, user, [d['id']], '', '',
context)[d['id']]
                        if code:
                                name = '[%s] %s' % (code,name)
                        if d['variants']:
                                name = name + ' - %s' % (d['variants'],)
                        return (d['id'], name)
                result = map(_name_get, self.read(cr, user, ids, ['variants']))
                return result

        def name_search(self, cr, user, name, args=[], operator='ilike',
context={}):
                ids = self.search(cr, user, [('name',operator,name)]+ args)
                ids += self.search(cr, user, [('default_code','=',name)]+ args)
                return self.name_get(cr, user, ids)

        def price_get(self, cr, uid, ids, ptype='list'):
                result = self.read(cr, uid, ids)
                result2 = {}
                for res in result:
                        result2[res['id']] =
(res[ptype+'_price']*(1.0+(res[ptype+'_price_margin'] or
0.0)))+(res[ptype+'_price_extra'] or 0.0)
                return result2
product_product()

def rounding(f, r):
        if not r:
                return f
        return round(f / r) * r

#----------------------------------------------------------
# Price lists
#----------------------------------------------------------

class product_pricelist(osv.osv):
        _name = "product.pricelist"
        _description = "Pricelist"
        _columns = {
                'name': fields.char('Name',size=64, required=True),
                'active': fields.boolean('Active'),
                'version_id': fields.one2many('product.pricelist.version',
'pricelist_id', 'Pricelist Versions')
        }
        _defaults = {
                'active': lambda x,y,z: 1,
        }

        def price_get(self, cr, uid, ids, prod_id, qty, type='list'):
                result = {}

                # TODO FIXME
                for id in ids:
                        cr.execute('select * from product_pricelist_version 
where
pricelist_id=%d and active=True order by id limit 1', (id,))
                        plversion = cr.dictfetchone()
                        if not plversion:
                                raise 'pricelist', 'No active version for this 
pricelist !\nPlease
create or active one.'

                        cr.execute('select id,categ_id from product_template 
where
id=(select product_tmpl_id from product_product where id=%d)',
(prod_id,))
                        tmpl_id,categ = cr.fetchone()
                        categ_ids = []
                        while categ:
                                categ_ids.append(str(categ))
                                cr.execute('select parent_id from 
product_category where id=%d',
(categ,))
                                categ = cr.fetchone()[0]
                        if categ_ids:
                                categ_where = '(categ_id in 
('+','.join(categ_ids)+'))'
                        else:
                                categ_where = '(categ_id is null)'

                        cr.execute('select * from product_pricelist_item where
(product_tmpl_id is null or product_tmpl_id=%d) and '+categ_where+' and
price_version_id=%d and (min_quantity is null or min_quantity<=%d)
order by priority limit 1', (tmpl_id, plversion['id'], qty))
                        res = cr.dictfetchone()
                        if res:

                                if res['base_pricelist_id'] and 
res['base']=='pricelist':
                                        price = self.price_get(cr, uid, 
[res['base_pricelist_id']],
prod_id, qty, type)[res['base_pricelist_id']]
                                        price_limit = self.price_get(cr, uid, 
[res['base_pricelist_id']],
prod_id, qty, 'limit')[res['base_pricelist_id']]
                                else:
                                        price = 
self.pool.get('product.product').price_get(cr, uid,
[prod_id], type)[prod_id]
                                        price_limit = 
self.pool.get('product.product').price_get(cr, uid,
[prod_id], 'limit')[prod_id]

                                price = price * 
(1.0-(res[type+'_price_discount'] or 0.0))
                                price=rounding(price, res[type+'_price_round'])
                                price += (res[type+'_price_surcharge'] or 0.0)
                                if res[type+'_price_min_margin']:
                                        price = max(price, 
price_limit+res[type+'_price_min_margin'])
                                if res[type+'_price_max_margin']:
                                        price = min(price, 
price_limit+res[type+'_price_max_margin'])
                        else:
                                price=False
                        result[id] = price

                return result
product_pricelist()

class product_pricelist_version(osv.osv):
        _name = "product.pricelist.version"
        _description = "Pricelist Version"
        _columns = {
                'pricelist_id': fields.many2one('product.pricelist', 'Price 
List',
required=True),
                'name': fields.char('Name', size=64, required=True),
                'active': fields.boolean('Active'),
                'items_id': fields.one2many('product.pricelist.item',
'price_version_id', 'Price List Items', required=True),
                'date_start': fields.date('Start Date'),
                'date_end': fields.date('End Date')
        }
        _defaults = {
                'active': lambda x,y,z: 1,
        }
product_pricelist_version()

class product_pricelist_item(osv.osv):
        _name = "product.pricelist.item"
        _description = "Pricelist item"
        _order = "priority"
        _defaults = {
                'list_price_base': lambda x,y,z: 'list',
                'standard_price_base': lambda x,y,z: 'standard',
                'limit_price_base': lambda x,y,z: 'limit',
                'min_quantity': lambda x,y,z: 1,
                'priority': lambda x,y,z: 5,
        }
        _columns = {
                'name': fields.char('Name', size=64, required=True),
                'price_version_id': fields.many2one('product.pricelist.version',
'Price List Version', required=True),
                'product_tmpl_id': fields.many2one('product.template', 'Product
Template'),
                'categ_id': fields.many2one('product.category', 'Product 
Category'),

                'min_quantity': fields.integer('Min. Quantity', required=True),
                'priority': fields.integer('Priority', required=True),
                'base':
fields.selection((('product','Product'),('pricelist','Pricelist')),
'Based on', required=True),
                'base_pricelist_id': fields.many2one('product.pricelist', 'Base 
Price
List'),

                'list_price_base':
fields.selection((('list','List'),('standard','Standard'),('limit','Limit')),'List
Price Base', required=True),
                'list_price_surcharge': fields.float('List Price Surcharge'),
                'list_price_discount': fields.float('List Price Discount'),
                'list_price_round': fields.float('List Price Rounding'),
                'list_price_min_margin': fields.float('List Price Min. Margin'),
                'list_price_max_margin': fields.float('List Price Max. Margin'),

                'standard_price_base':
fields.selection((('list','List'),('standard','Standard'),('limit','Limit')),'Standard
Price Base', required=True),
                'standard_price_surcharge': fields.float('Standard Price 
Surcharge'),
                'standard_price_discount': fields.float('Standard Price 
Discount'),
                'standard_price_round': fields.float('Standard Price Rounding'),
                'standard_price_min_margin': fields.float('Standard Price Min.
Margin'),
                'standard_price_max_margin': fields.float('Standard Price Max.
Margin'),

                'limit_price_base':
fields.selection((('list','List'),('standard','Standard'),('limit','Limit')),'Limit
Price Base', required=True),
                'limit_price_surcharge': fields.float('Limit Price Surcharge'),
                'limit_price_discount': fields.float('Limit Price Discount'),
                'limit_price_round': fields.float('Limit Price Rounding'),
                'limit_price_min_margin': fields.float('Limit Price Min. 
Margin'),
                'limit_price_max_margin': fields.float('Limit Price Max. 
Margin'),
        }
product_pricelist_item()

-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to