Odoo - 在另一个模型中调用方法

Odoo - Call method in another model

我想通过点击销售订单中的确认按钮来调用一个方法来更新相应合作伙伴的帐户。

为此我在伙伴模型中定义了工作方式:

class res_partner(orm.Model):
    _inherit = 'res.partner'


    def update_account(self, cr, uid, partner_id, account_type, context, force_checked=None):

        if account_type not in ('receivable', 'payable'):
            return

        company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
        parent_account = getattr(company, 'parent_%s_account_id' % account_type)
        if not parent_account:
            return

        partner = self.browse(cr, uid, partner_id, context)
        if account_type == 'receivable':
            checked = partner.customer
        else:
            checked = partner.supplier
        partner_account = getattr(partner, 'property_account_%s' % account_type)

        if not force_checked is None:
            checked = force_checked

        if partner_account:
            if checked:
                # If account already exists, just check if we need to update account name.
                if partner_account.name != partner.name:
                    # We will only update account name if no other partner is using the same account.
                    value = 'account.account,%d' % partner_account.id
                    partners = self.pool.get('ir.property').search(
                        cr, uid, [('res_id', '!=', False),
                                  ('value_reference', '=', value)],
                        context=context)
                    if len(partners) == 1:
                        self.pool.get('account.account').write(
                            cr, uid, [partner_account.id], {
                                'name': partner.name,
                            }, context)
                        return

            # If it's not possible to unlink the account we will rollback this change
            # so the property remains the same. Note that we cannot try to unlink first, 
            # because in this case it would always fail because of the fact that it's set
            # as the account in the partner.
            cr.execute('SAVEPOINT remove_account')
            self.write(cr, uid, [partner_id], {
                'property_account_%s' % account_type: False,
            }, context)
            try:
                # Unlink may raise an exception if the account is already set in another partner
                # or if it has account moves.
                if partner_account.name == partner.name:
                    self.pool.get('account.account').unlink(cr, uid, [partner_account.id], context)
            except orm.except_orm:
                cr.execute('ROLLBACK TO SAVEPOINT remove_account')

            cr.execute('RELEASE SAVEPOINT remove_account')

        if not checked:
            return

        sequence_obj = self.pool.get('ir.sequence')
        sequence_id = sequence_obj.search(cr, uid, [('code', '=', 'res.partner')],
                                          context=context)
        sequence = sequence_obj.browse(cr, uid, sequence_id,
                                       context=context)[0]

        code = partner.ref

        account_id = self.pool.get('account.account').search(cr, uid, [('code', '=', code)], context=context)
        if account_id:
            account_id = account_id[0]
        else:
            account_id = self.pool.get('account.account').create(cr, uid, {
                'name': partner.name,
                'code': code,
                'parent_id': parent_account.id,
                'user_type': 2,
                'reconcile': True,
                'type': account_type,
            }, context)
        self.write(cr, uid, [partner_id], {
            'property_account_%s' % account_type: account_id,
        }, context)

我想通过点击确认按钮调用该方法,所以我这样做:

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def action_button_confirm(self, cr, uid, ids, context=None):
        sale_order = self.pool.get('sale.order').browse(cr, uid, ids)
        partner = self.pool.get('res.partner').browse(cr, uid, sale_order.partner_id, context=context)

        partner.update_account(cr, uid, partner.id, 'receivable', context)

        return super(SaleOrder, self).action_button_confirm(cr, uid, ids, context=None)

但我总是收到这个错误:

Odoo Server Error
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 544, in _handle_exception
    return super(JsonRequest, self)._handle_exception(exception)
  File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 581, in dispatch
    result = self._call_function(**self.params)
  File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 317, in _call_function
    return checked_call(self.db, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/openerp/service/model.py", line 118, in wrapper
    return f(dbname, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 314, in checked_call
    return self.endpoint(*a, **kw)
  File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 810, in __call__
    return self.method(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 410, in response_wrap
    response = f(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/openerp/addons/web/controllers/main.py", line 948, in call_button
    action = self._call_kw(model, method, args, {})
  File "/usr/lib/python2.7/dist-packages/openerp/addons/web/controllers/main.py", line 936, in _call_kw
    return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 268, in wrapper
    return old_api(self, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/openerp/addons/portal_sale/portal_sale.py", line 67, in action_button_confirm
    return super(sale_order, self).action_button_confirm(cr, uid, ids, context=context)
  File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 268, in wrapper
    return old_api(self, *args, **kwargs)
  File "/Odoo/OdooV8/partner_auto_account/sale_order.py", line 15, in action_button_confirm
    partner.update_account(cr, uid, partner.id, 'receivable', context)
  File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 266, in wrapper
    return new_api(self, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 508, in new_api
    result = method(self._model, cr, uid, *args, **old_kwargs)
TypeError: update_account() takes at most 7 arguments (9 given)

那么米特是什么? 我没有超过 9 个参数... 哪里出了问题?

你不传递 9 个参数,框架传递。

调用方法如下:

partner.update_account(partner.id, 'receivable', context)

如果您检查堆栈跟踪,您会看到:

  File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 508, in new_api
    result = method(self._model, cr, uid, *args, **old_kwargs)

框架已经为您传递了 cr 和 uid 参数。

如果您使用 Odoo 的新 API,您不必传递标准变量 self、cr、uid、context,odoo 默认会为您传递,

我懒得阅读你所有的代码,但我猜你正在使用表单上的按钮调用方法并且你收到错误:update_account() takes at most 7 arguments (9 given).

所以,问题是为什么?也许这对我很粗鲁,但你应该在开始使用 odoo 之前阅读官方文档。答案是你没有使用任何函数装饰器。要了解有关装饰器的更多信息,请遵循此 link.

因此,如果您需要使用旧的 API,您应该使用 @api.model,在任何其他情况下您应该使用 @api.one@api.multi。这两者的区别是ids。在 @api.multi 中,它也通过了 ids,所以你有一个记录集,在 @api.one 的情况下,你有一个记录。

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    @api.multi #because you were passing ids too
    def action_button_confirm(self):
        # self is here recordset of ids already and besides 
        # self.pool.get is an old api you shouldn't use it, 
        # use self.env instead
        for sale_order in self: 
            partner = sale_order.partner_id     
            # you don't need to pass partner id   
            partner.update_account('receivable')
        return super(SaleOrder, self).action_button_confirm()

我无法修复您所有的代码,但例如,我修复的代码就足够了。

使用新的API

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    @api.multi
    def action_button_confirm(self):
        assert len(self) == 1, 'This option should only be used for a single id at a time.'
        partner.update_account(partner_id=self.partner_id.id, account_type='receivable')
        return super(SaleOrder, self).action_button_confirm()

对于任何寻找通用答案的人,这就是我在 odoo 10 中调用另一个模型方法的方式:

self.env['my.model'].some_method()