Stack Exchange
Error"AttributeError: 'product.pricelist' object has no attribute 'get_product_pricelist'
i'm using odoo 9 and i want to install module "product_print_zpl_barcode" with add a wizard on product variant which allows to generate and print a product barcode on a ZPL printer . When i press on the button "Print barcode" an error shows which said " AttributeError: 'product.pricelist' object has no attribute 'get_product_pricelist' " Any help please ??
Product.xml 
 <?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_normal_form_view" model="ir.ui.view">
<field name="name">generate.weight.price.barcode.product.product.form</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view" />
<field name="arch" type="xml">
    <header position="inside">
        <button name="%(product_print_zpl_barcode.product_print_zpl_barcode_action)d" type="action" string="Print Barcode"/>
    </header>
</field>
</record>
</odoo>

product_print_zpl_barcode.py
-- coding: utf-8 --
 from openerp import models, fields, api, _
 from openerp.exceptions import UserError
 from openerp.tools import float_compare, float_is_zero
 import openerp.addons.decimal_precision as dp
 import base64
 import re


 class ProductPrintZplBarcode(models.TransientModel):
_name = 'product.print.zpl.barcode'
_description = 'Generate and print product barcodes in ZPL'

@api.model
def default_get(self, fields_list):
    res = super(ProductPrintZplBarcode, self).default_get(fields_list)
    assert self._context.get('active_model') == 'product.product',\
        'wrong active_model, should be product.product'
    product_id = self._context.get('active_id')
    product = self.env['product.product'].browse(product_id)
    if not product:
        raise UserError(_('Missing Product'))
    if not product.barcode:
        raise UserError(_(
            "Product '%s' doesn't have a barcode") % product.display_name)
    nomenclature = self.env.ref('barcodes.default_barcode_nomenclature')
    company = self.env.user.company_id
    posconfig = self.env['pos.config'].sudo().search(
        [('company_id', '=', company.id)], limit=1)
    if posconfig:
        pricelist = posconfig.pricelist_id
    else:
        pricelist = self.env['product.pricelist'].search([
            '|', ('company_id', '=', False),
            ('company_id', '=', company.id),
            ], limit=1)
    if not pricelist:
        raise UserError(_(
            "There are no pricelist in company %s ?") % company.name)

    printer = self.env['printing.printer'].get_default()
    res.update({
        'nomenclature_id': nomenclature.id,
        'pricelist_id': pricelist.id,
        'currency_id': pricelist.currency_id.id,
        'barcode': product.barcode,
        'product_name': product.name,
        'product_id': product_id,
        'zpl_printer_id': printer and printer.id or False,
    })
    return res

product_id = fields.Many2one(
    'product.product', string='Product', required=True, readonly=True)
uom_id = fields.Many2one(
    related='product_id.uom_id', readonly=True)
# 1 line = un peu moins de 30
product_name = fields.Char('Product Label', required=True, size=56)
nomenclature_id = fields.Many2one(
    'barcode.nomenclature', 'Barcode Nomenclature', required=True)
rule_id = fields.Many2one(
    'barcode.rule', string='Barcode Rule', readonly=True,
    compute='_compute_rule_id')
barcode_type = fields.Selection(
    related='rule_id.type', readonly=True, string="Barcode Type")
label_size = fields.Selection([
    ('38x25', '38x25 mm'),
    ], required=True, default='38x25', string='Label Size')
pricelist_id = fields.Many2one(
    'product.pricelist', string='Pricelist', required=True)
currency_id = fields.Many2one(
    related='pricelist_id.currency_id', readonly=True)
# TODO: for the moment, we only support weight, but...
quantity = fields.Float(digits=dp.get_precision('Stock Weight'))
price_uom = fields.Monetary(
    readonly=True, string="Price per Unit of Measure",
    compute='_compute_price')  # given by pricelist
price = fields.Monetary(compute='_compute_price', readonly=True)
currency_id = fields.Many2one('res.currency', string='Currency')
state = fields.Selection([
    ('step1', 'Step1'),
    ('step2', 'Step2'),
    ], default='step1', readonly=True)
zpl_file = fields.Binary(string='ZPL File', readonly=True)
zpl_filename = fields.Char('ZPL Filename')
barcode = fields.Char(readonly=True)
copies = fields.Integer(
    string='Number of Labels', default=1, required=True)
zpl_printer_id = fields.Many2one(
    'printing.printer', string='ZPL Printer')

@api.depends('pricelist_id', 'quantity', 'product_id')
def _compute_price(self):
    # for regular barcodes
    for wiz in self:
        if wiz.pricelist_id and wiz.product_id:
            price_uom = wiz.pricelist_id.get_product_pricelist(
                wiz.product_id, 1, False)
            wiz.price_uom = price_uom
            wiz.price = price_uom * wiz.quantity
    return wiz.price

@api.one
@api.depends('nomenclature_id')
def _compute_rule_id(self):
    match_rule = False
    if self.nomenclature_id and self.barcode:
        for rule in self.nomenclature_id.rule_ids:
            match = self.nomenclature_id.match_pattern(
                self.barcode, rule.pattern)
            if match.get('match'):
                match_rule = rule.id
                break
    self.rule_id = match_rule

def _prepare_price_weight_barcode_type(self):
    dpo = self.env['decimal.precision']
    bno = self.env['barcode.nomenclature']
    prec = dpo.precision_get('Stock Weight')
    value = self.quantity
    pbarcode = self.barcode
    if float_is_zero(value, precision_digits=prec):
        raise UserError(_(
            "The quantity (%s) must be positive !") % value)
    # check prefix
    pattern = self.rule_id.pattern
    if '{' not in pattern:
        raise UserError(_(
            "The barcode rule '%s' has a pattern '%s' which doesn't "
            "contain a integer and decimal part between '{}'.")
            % (self.rule_id.name, pattern))
    prefix = pattern.split('{')[0]
    assert len(prefix) >= 1
    if len(prefix) > len(pbarcode):
        raise UserError(_(
            "The barcode of the product (%s) has %d characters, "
            "which is smaller than the %d characters of the prefix "
            "of the barcode pattern (%s).")
            % (pbarcode, len(pbarcode), len(prefix), prefix))
    barcode = pbarcode[0:len(prefix)]
    # print "barcode=", barcode
    # print "pattern=", pattern
    m = re.search('\{N+D+\}', pattern)
    # print "m=", m
    assert m
    pattern_val = m.group(0)
    pattern_val = pattern_val[1:-1]
    # print "pattern_val=", pattern_val
    max_value = 10**pattern_val.count('N')
    if float_compare(value, max_value, precision_digits=prec) != -1:
        raise UserError(_(
            "The value to encode in the barcode (%s) is superior "
            "to the maximum value allowed by the barcode pattern (%s).")
            % (value, max_value))
    value_u = unicode(value)
    value_u_split = value_u.split('.')
    assert len(value_u_split) == 2
    value_n = value_u_split[0]
    value_d = value_u_split[1]
    assert len(value_n) <= pattern_val.count('N')
    barcode += value_n.zfill(pattern_val.count('N'))
    # end fill doesn't exists... so:
    # 1) make sure we have enough 0 after
    value_d_ext = value_d + '0' * pattern_val.count('D')
    # 2) cut at the right size
    barcode += value_d_ext[0:pattern_val.count('D')]
    # print "barcode=", barcode
    # Add checksum
    if self.rule_id.encoding == 'ean13':
        barcode = bno.sanitize_ean(barcode)
        # print "barcode FINAL=", barcode
    zpl_unicode = self._price_weight_barcode_type_zpl() % {
        'product_name': self.product_name,
        'ean13_no_checksum': barcode[:12],
        'price_uom': self.price_uom,
        'price': self.price,
        'currency_symbol': self.currency_id.symbol,
        'copies': self.copies,
        'quantity': value,
        'uom_name': self.uom_id.name,
    }
    zpl_encoded = zpl_unicode.encode('utf-8')
    vals = {
        'zpl_file': zpl_encoded.encode('base64'),
        'barcode': barcode,
        }
    return vals

@api.model
def _price_weight_barcode_type_zpl(self):
    label = u"""
 ^XA
 ^CI28
 ^PW304
 ^LL200
 ^LH0,20
 ^CF0,30
 ^FO15,0^FB270,1,0,C^FD%(price).2f %(currency_symbol)s^FS
 ^CF0,20
 ^FO15,30^FB270,3,0,C^FD%(product_name)s^FS
 ^CF0,25
 ^FO15,75^FB270,1,0,C^FD%(quantity).3f %(uom_name)s    %(price_uom).2f % 
  (currency_symbol)s/%(uom_name)s^FS
 ^FO60,110^BEN,50^FD%(ean13_no_checksum)s^FS
 ^PQ%(copies)s
 ^XZ
 """
    return label

@api.model
def _product_barcode_type_zpl(self):
    label = u"""
  ^XA
  ^CI28
  ^PW304
  ^LL200
  ^LH0,20
  ^CF0,30
  ^FO15,0^FB270,1,0,C^FD%(price_uom).2f %(currency_symbol)s^FS
  ^CF0,20
  ^FO15,30^FB270,3,0,C^FD%(product_name)s^FS
  ^FO60,100^BEN,60^FD%(ean13_no_checksum)s^FS
  ^PQ%(copies)s
  ^XZ
  """
    return label

def _prepare_product_barcode_type(self):
    zpl_unicode = self._product_barcode_type_zpl() % {
        'product_name': self.product_name,
        'ean13_no_checksum': self.barcode[:12],
        'price_uom': self.price_uom,
        'currency_symbol': self.currency_id.symbol,  # symbol is a required field
        'copies': self.copies,
    }
    zpl_encoded = zpl_unicode.encode('utf-8')
    vals = {
        'zpl_file': zpl_encoded.encode('base64'),
        'barcode': self.barcode,  # unchanged
        }
    return vals

def generate(self):
    assert self.barcode
    if len(self.barcode) != 13:
        raise UserError(_(
            "This wizard only supports EAN13 for the moment. Barcode '%s' "
            "has %d digits instead of 13") % (
            self.barcode,
            len(self.barcode)))
    if not self.copies:
        raise UserError(_("The number of copies cannot be 0"))
    if self.barcode_type in ('price', 'weight'):
        vals = self._prepare_price_weight_barcode_type()
    elif self.barcode_type == 'product':
        vals = self._prepare_product_barcode_type()
    else:
        raise UserError(_(
            "Barcode Type %s is not supported for the moment")
            % self.barcode_type)
    vals.update({
        'state': 'step2',
        'zpl_filename': 'barcode_%s.zpl' % vals['barcode'],
        })
    self.write(vals)
    action = self.env['ir.actions.act_window'].for_xml_id(
        'product_print_zpl_barcode',
        'product_print_zpl_barcode_action')
    action.update({
        'res_id': self.id,
        'context': self._context,
        'views': False})
    return action

def print_zpl(self):
    if not self.zpl_printer_id:
        raise UserError(_(
            "You must select a ZPL Printer."))
    self.zpl_printer_id.print_document(
        self.zpl_filename, base64.decodestring(self.zpl_file), 'raw')
    action = True
    if self._context.get('print_and_new'):
        action = self.env['ir.actions.act_window'].for_xml_id(
            'product_print_zpl_barcode',
            'product_print_zpl_barcode_action')
        action.update({
            'views': False,
            'context': self._context,
            })
    return action

Traceback 
    Traceback (most recent call last):
    File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\http.py", line 
   650, in _handle_exception
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\http.py", line 
   687, in dispatch
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\http.py", line 
   323, in _call_function
   File "D:\Projet_Odoo\Odoo 9.0- 
   20180426\server\.\openerp\service\model.py", line 118, in wrapper
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\http.py", line 
   316, in checked_call
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\http.py", line 
   966, in __call__
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\http.py", line 
   516, in response_wrap
   File "D:\Projet_Odoo\Odoo 9.0- 
   20180426\server\openerp\addons\web\controllers\main.py", line 896, in 
   call_kw
   File "D:\Projet_Odoo\Odoo 9.0- 
   20180426\server\openerp\addons\web\controllers\main.py", line 888, in 
   _call_kw
    File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\api.py", line 
   250, in wrapper
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\api.py", line 
   381, in old_api
   File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\models.py", line 
  6067, in onchange
  File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\models.py", line 
  5770, in __getitem__
 File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\fields.py", line 
 834, in __get__
 File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\fields.py", line 
949, in determine_draft_value
File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\fields.py", line 
895, in compute_value
File "D:\Projet_Odoo\Odoo 9.0-20180426\server\.\openerp\fields.py", line 
885, in _compute_value
 File "D:\Projet_Odoo\Odoo 9.0-20180426\server\openerp\addons\product_print_zpl_barcode\models\product_print_zpl_barcode.py", line 98, in _compute_price
 AttributeError: 'product.pricelist' object has no attribute 
 'get_product_pricelist'


Check if the method get_product_pricelist exists in the model product.pricelist

Yes it exists
def _get_product_pricelist(self, cr, uid, ids, context=None):
result = set()
for pricelist in self.pool['product.pricelist'].browse(cr, uid, ids, context=context):
for item in pricelist.item_ids:
result.add(item.id)
return list(result)

You said it yourself, but it looks like you just missed it.

Yes it exists
def _get_product_pricelist(...):
    ...


However, _get_product_pricelist is not the same as what you're calling, which is get_product_pricelist. 
You are missing the underscore prior to the method name.
price_uom = wiz.pricelist_id._get_product_pricelist(
    ...                      ^


Thanks i modified it and know it shows "AttributeError: 'product.pricelist' object has no attribute '_get_product_pricelist' "

That's because the _get_product_pricelist method belongs to the product.pricelist.item Class. What are you trying to do? It seems like you want to get the price of a product from the pricelist. Maybe you should try using price_get from the product.pricelist Class. Such as: wiz.pricelist_id.price_get(wiz.product_id, 1)

Yes i want to get the price of  product

Try the price_get call I mentioned in the last comment.

Ok , Thanks , it works And there  is another error :D              File "psycopg2\extensions.pyc", line 129, in getquoted
ProgrammingError: can't adapt type 'product.product'

You’ll have to use wiz.product_id.id because price_get expects an integer.

A new error : TypeError: float() argument must be a string or a number

Yes   ligne  File "D:\Projet_Odoo\Odoo 9.0-20180426\server\openerp\addons\product_print_zpl_barcode\models\product_print_zpl_barcode.py", line 100, in _compute_price   File "D:\Projet_Odoo\Odoo 9.0-20180426\server.\openerp\fields.py", line 847, in set
File "D:\Projet_Odoo\Odoo 9.0-20180426\server.\openerp\fields.py", line 1177, in convert_to_cache

I see you opened a new question so I will check it out there. Please upvote and mark as accepted if my answer solved your original question here.

Thank you very much
