llabusch93
llabusch93

Reputation: 33

Odoo - Call method in another model

I want to call a method by clicking on the confirmation button in sale orders to update the account of the corresponding partner.

Therefor I have defined the working method in the partner 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)

I want to call the method by clicking on the conformation button, so I do it like this:

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)

But I get this error all the time:

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)

So what's the metter? I do not pass over 9 arguments... What went wrong?

Upvotes: 1

Views: 10420

Answers (5)

Dachi Darchiashvili
Dachi Darchiashvili

Reputation: 769

I'm too lazy to read all your code, but I guess you are calling method using a button on the form and you are getting error: update_account() takes at most 7 arguments (9 given).

So, there is the question why? Maybe it's rude of me, but you should read official documentation before starting working on odoo. The answer is you are not using any function decorators. To learn more about decorators follow this link.

So if you need to use old API, you should use @api.model and in any other case you should use @api.one or @api.multi. The difference between this two is ids. In @api.multi it passes ids too so you have a recordset and in case of @api.one you have a single record.

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()

I can't fix all your code, but for example it's enough what I fixed.

Upvotes: 1

Fractalf
Fractalf

Reputation: 5319

For anyone looking for a generic answer this is how I call another models method in odoo 10:

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

Upvotes: 3

Kenly
Kenly

Reputation: 26678

Use new 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()

Upvotes: 2

zaizousf
zaizousf

Reputation: 93

If you are using the new API of Odoo, you don't have to pass standard variables self, cr,uid,context, odoo do it for your by default,

Upvotes: 0

gdaramouskas
gdaramouskas

Reputation: 3747

You do not pass 9 argument, the framework does.

Call the method like this:

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

If you check on the stack trace you will see that:

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

The framework already passes the cr and uid parameters for you.

Upvotes: 0

Related Questions