首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TypeError:不可散列类型:'list‘|将Odoo v8移植到Odoo 12

TypeError:不可散列类型:'list‘|将Odoo v8移植到Odoo 12
EN

Stack Overflow用户
提问于 2019-08-03 04:54:18
回答 1查看 394关注 0票数 1

我正在尝试读取发票记录,但我在下一个问题中遇到了问题,下面是我的终端日志:

代码语言:javascript
复制
Odoo Server Error

Traceback (most recent call last):
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 654, in _handle_exception
    return super(JsonRequest, self)._handle_exception(exception)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 312, in _handle_exception
    raise pycompat.reraise(type(exception), exception, sys.exc_info()[2])
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/tools/pycompat.py", line 87, in reraise
    raise value
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 696, in dispatch
    result = self._call_function(**self.params)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 344, in _call_function
    return checked_call(self.db, *args, **kwargs)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/service/model.py", line 97, in wrapper
    return f(dbname, *args, **kwargs)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 337, in checked_call
    result = self.endpoint(*a, **kw)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 939, in __call__
    return self.method(*args, **kw)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/http.py", line 517, in response_wrap
    response = f(*args, **kw)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/addons/web/controllers/main.py", line 966, in call_button
    action = self._call_kw(model, method, args, {})
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/addons/web/controllers/main.py", line 954, in _call_kw
    return call_kw(request.env[model], method, args, kwargs)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/api.py", line 749, in call_kw
    return _call_kw_multi(method, model, args, kwargs)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/api.py", line 736, in _call_kw_multi
    result = method(recs, *args, **kwargs)
  File "/home/desarrollo/Documentos/odoo-12/custom/l10n-ve/l10n_vzla_dcnote/wizard/account_invoice_debit.py", line 178, in invoice_debit
    return self.compute_debit()
  File "/home/desarrollo/Documentos/odoo-12/custom/l10n-ve/l10n_vzla_dcnote/wizard/account_invoice_debit.py", line 111, in compute_debit
    'journal_id', 'period_id'])
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/models.py", line 2747, in read
    fields = self.check_field_access_rights('read', fields)
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/models.py", line 2722, in check_field_access_rights
    invalid_fields = {name for name in fields if not valid(name)}
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/models.py", line 2722, in <setcomp>
    invalid_fields = {name for name in fields if not valid(name)}
  File "/home/desarrollo/Documentos/odoo-12/odoo-12.0/odoo/models.py", line 2713, in valid
    field = self._fields.get(fname)
TypeError: unhashable type: 'list'

我尝试删除一些字段,但仍然收到错误。

下面是我的自定义模块:

代码语言:javascript
复制
# coding: utf-8
import time

from odoo import api, fields, models, _
from odoo.tools.translate import _
from odoo.osv import osv

class AccountInvoiceDebit(models.TransientModel):

    """Debits Note from Invoice"""

    _name = "account.invoice.debit"
    _description = "Invoice Debit Note"

    date = fields.Date('Operation date',
                        help='This date will be used as the invoice date '
                                'for Refund Invoice and Period will be '
                                'chosen accordingly!')
    period = fields.Many2one('account.period', 'Force period')
    journal_id = fields.Many2one('account.journal',
                                    'Refund Journal',
                                    help='You can select here the journal '
                                        'to use for the refund invoice '
                                        'that will be created. If you '
                                        'leave that field empty, it will '
                                        'use the same journal as the '
                                        'current invoice.')
    description = fields.Char('Description', size=128, required=True)
    comment = fields.Text('Comment', required=True)

    def _get_journal(self, cr, uid, context=None):
        obj_journal = self.pool.get('account.journal')
        user_obj = self.pool.get('res.users')
        if context is None:
            context = {}
        inv_type = context.get('type', 'out_invoice')
        company_id = user_obj.browse(
            cr, uid, uid, context=context).company_id.id
        type = (inv_type == 'out_invoice') and 'sale_refund' or \
               (inv_type == 'out_refund') and 'sale' or \
               (inv_type == 'in_invoice') and 'purchase_refund' or \
               (inv_type == 'in_refund') and 'purchase'
        journal = obj_journal.search(cr, uid, [('type', '=', type), (
            'company_id', '=', company_id)], limit=1, context=context)
        return journal and journal[0] or False

    _defaults = {
        'date': lambda *a: time.strftime('%Y-%m-%d'),
        'journal_id': _get_journal,
    }

    def _get_period(self, cr, uid, context={}):
        """
        Return  default account period value
        """
        account_period_obj = self.pool.get('account.period')
        ids = account_period_obj.find(cr, uid, context=context)
        period_id = False
        if ids:
            period_id = ids[0]
        return period_id

    def _get_orig(self, cr, uid, inv, ref, context={}):
        """
        Return  default origin value
        """
        nro_ref = ref
        if inv.type == 'out_invoice':
            nro_ref = inv.number
        orig = _('INV:') + (nro_ref or '') + _('- DATE:') + (
            inv.date_invoice or '') + (' TOTAL:' + str(inv.amount_total) or '')
        return orig

    @api.model
    def compute_debit(self, context=None):
        """
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param ids: the account invoice refund’s ID or list of IDs

        """
        inv_obj = self.env['account.invoice']
        mod_obj = self.env['ir.model.data']
        act_obj = self.env['ir.actions.act_window']
        inv_tax_obj = self.env['account.invoice.tax']
        inv_line_obj = self.env['account.invoice.line']
        res_users_obj = self.env['res.users']
        record = self._context.get('active_ids')
        if context is None:
            context = {}

        for form in self.browse(self):
            created_inv = []
            date = False
            period = False
            description = False
            company = res_users_obj.company_id
            journal_id = self.journal_id
            for inv in inv_obj.browse(record):


                # we get original data of invoice to create a new invoice that
                # is the copy of the original
                invoice = inv.read([record],
                                       ['name', 'type', 'number', 'reference',
                                        'comment', 'date_due', 'partner_id',
                                        'partner_insite', 'partner_contact',
                                        'partner_ref', 'payment_term',
                                        'account_id', 'currency_id',
                                        'invoice_line', 'tax_line',
                                        'journal_id', 'period_id'])
                invoice = invoice[0]
                del invoice['id']
                invoice_lines = inv_line_obj.browse(
                    cr, uid, invoice['invoice_line'], context=context)
                invoice_lines = inv._refund_cleanup_lines(
                    cr, uid, invoice_lines, context=context)
                tax_lines = inv_tax_obj.browse(
                    cr, uid, invoice['tax_line'], context=context)
                tax_lines = inv_obj._refund_cleanup_lines(
                    cr, uid, tax_lines, context=context)
                # Add origin, parent and comment values
                orig = self._get_orig(cr, uid, inv, invoice[
                                      'reference'], context)
                invoice.update({
                    'type': inv.type == 'in_invoice' and 'in_refund' or
                    inv.type == 'out_invoice' and 'out_refund',
                    'date_invoice': date,
                    'state': 'draft',
                    'number': False,
                    'invoice_line': invoice_lines,
                    'tax_line': tax_lines,
                    'period_id': period,
                    'parent_id': inv.id,
                    'name': description,
                    'origin': orig,
                    'comment': form['comment']
                })
                # take the id part of the tuple returned for many2one fields
                for field in ('partner_id', 'account_id', 'currency_id',
                              'payment_term', 'journal_id'):
                    invoice[field] = invoice[field] and invoice[field][0]
                # create the new invoice
                inv_id = inv_obj.create(self, invoice, {})
                # we compute due date
                if inv.payment_term.id:
                    data = inv_obj.onchange_payment_term_date_invoice(
                        cr, uid, [inv_id], inv.payment_term.id, date)
                    if 'value' in data and data['value']:
                        inv_obj.write(cr, uid, [inv_id], data['value'])
                created_inv.append(inv_id)
            # we get the view id
            """
            xml_id = (inv_obj.type == 'out_refund') and 'action_invoice_tree1' or \
                     (inv_obj.type == 'in_refund') and 'invoice_supplier_form' or \
                     (inv_obj.type == 'out_invoice') and 'action_invoice_out_refund' or \
                     (inv_obj.type == 'in_invoice') and 'action_invoice_in_refund'
            """

            raise osv.except_osv(created_inv)
            # we get the model
            """
            result = mod_obj.get_object_reference('account.invoice', xml_id)
            id = result and result[1] or False
            # we read the act window
            result = act_obj.read(cr, uid, id, context=context)
            # we add the new invoices into domain list
            invoice_domain = eval(result['domain'])
            invoice_domain.append(('id', 'in', created_inv))
            result['domain'] = invoice_domain
            """
            return True

    @api.multi
    def invoice_debit(self):
        #ids = self._context('active_ids')
        #id_inv = self._context.get('active_ids')
        return self.compute_debit()

我希望读取发票来创建一个具有一些更改的值的副本,因此我强制执行了一个raise错误,以确保将创建该副本。

EN

回答 1

Stack Overflow用户

发布于 2019-08-19 01:16:23

首先,你使用了api.model意味着你正在使用新的API。我对这一行感到困惑:

代码语言:javascript
复制
 for form in self.browse(self):

有了api.model,self总是一个空的集合,从来没有尝试过这一点,我想知道为什么你会在第一次玩的循环中。

我认为您需要将其更改为api.multi,并删除新api中的上下文参数,该参数位于自身中。

代码语言:javascript
复制
    self._context  or self.env.context

尝试一下,但这是一个简单的新API如何工作的说明,您不必每次都传递cr、id、context

代码语言:javascript
复制
@api.multi
def compute_debit(self):


     for form in self: # you don't have to browse self it's all read a Recordset
         .....
         .....
         .....

         for inv in inv_obj.browse(record): # this is okay because it's a list of ids you should browse to convert to recrodset
             # here you don't have to pass the id in the new api 
             invoice = inv.read(['name', 'type', 'number', 'reference',
                                    'comment', 'date_due', 'partner_id',
                                    'partner_insite', 'partner_contact',
                                    'partner_ref', 'payment_term',
                                    'account_id', 'currency_id',
                                    'invoice_line', 'tax_line',
                                    'journal_id', 'period_id'])

您正在将新api和旧api混合在一起?!!在你的代码中有很多你应该使用这两个中的一个。你会在代码上遇到很多问题,祝你好运。

举个例子

代码语言:javascript
复制
   inv._refund_cleanup_lines(
                cr, uid, invoice_lines, context=context)

我没有看到任何变量或参数cr或uid您明白了吗

例如,您需要做的不是像这样读取字段和调用方法:

代码语言:javascript
复制
       # no read at all you all ready have acces to fields
       inv._refund_cleanup_lines(inv.invoice_line)

希望你能明白我的意思。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57333323

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档