Ожидаемый синглтон: ошибка res.company() Odoo

Я создаю API, который ищет и отменяет запись в модели account.move. Я могу найти правильную запись и отменить ее, используя метод return_moves(). Однако всякий раз, когда я пытаюсь подтвердить обратную запись с помощью метода action_post(), я получаю ошибку «Ожидаемый синглтон: res.company()». Раньше я использовал метод action_post() в других моделях, таких как sale.order/account.move, и он работал нормально.

Код:

@http.route('/update_invoice', website = "false", auth='custom_auth', type='json', methods=['POST'])

#Searching for entry
invoice = request.env['account.move'].sudo().search([('matter_id','=',matterID),('account_id','=',accountID),('move_type','=','out_invoice'),('company_id','=',creditor.id)])
        if invoice:
            #Create Reversal
            move_reversal = request.env['account.move.reversal'].with_context(active_model = "account.move", active_ids=invoice.id).sudo().create({
                'date': intakeDate,
                'reason': 'Balance Adjustment',
                'journal_id': invoice.journal_id.id,
            })

            #Reverse Entry
            move_reversal.refund_moves()
            
            #Search for created reversed entry
            refundInvoice = request.env['account.move'].sudo().search([('name','=',"/"),('company_id','=',creditor.id),('move_type','=','out_refund')])

            if refundInvoice:
                _logger.info("Refund Invoice Found")

                #Error occurs
                refundInvoice.action_post()

Пользовательская авторизация:

    @classmethod
    def _auth_method_custom_auth(cls):
        access_token = request.httprequest.headers.get('Authorization')
        _logger.info(access_token)
        
        if not access_token:
            _logger.info('Access Token Missing')
            raise BadRequest('Missing Access Token')
        
        if access_token.startswith('Bearer '):
            access_token = access_token[7:]
            _logger.info(access_token)
            
        
        user_id = request.env["res.users.apikeys"]._check_credentials(scope='odoo.restapi', key=access_token)
        if not user_id:
            _logger.info('No user with api key found')
            raise BadRequest('Access token Invalid')

        request.update_env(user=user_id)

Выслеживать:

Traceback (most recent call last):
  File "/home/odoo/src/odoo/odoo/models.py", line 5841, in ensure_one
    _id, = self._ids
ValueError: not enough values to unpack (expected 1, got 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/odoo/src/odoo/odoo/http.py", line 2189, in __call__
    response = request._serve_db()
  File "/home/odoo/src/odoo/odoo/http.py", line 1765, in _serve_db
    return service_model.retrying(self._serve_ir_http, self.env)
  File "/home/odoo/src/odoo/odoo/service/model.py", line 133, in retrying
    result = func()
  File "/home/odoo/src/odoo/odoo/http.py", line 1792, in _serve_ir_http
    response = self.dispatcher.dispatch(rule.endpoint, args)
  File "/home/odoo/src/odoo/odoo/http.py", line 1996, in dispatch
    result = self.request.registry['ir.http']._dispatch(endpoint)
  File "/home/odoo/src/odoo/addons/website/models/ir_http.py", line 235, in _dispatch
    response = super()._dispatch(endpoint)
  File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 222, in _dispatch
    result = endpoint(**request.params)
  File "/home/odoo/src/odoo/odoo/http.py", line 722, in route_wrapper
    result = endpoint(self, *args, **params_ok)
  File "/home/odoo/src/user/account_ext/controllers/main.py", line 411, in update_invoice
    refundInvoice.action_post()
  File "/home/odoo/src/odoo/addons/sale/models/account_move.py", line 63, in action_post
    res = super(AccountMove, self).action_post()
  File "/home/odoo/src/enterprise/account_accountant/models/account_move.py", line 76, in action_post
    res = super().action_post()
  File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 4072, in action_post
    other_moves._post(soft=False)
  File "/home/odoo/src/enterprise/sale_subscription/models/account_move.py", line 13, in _post
    posted_moves = super()._post(soft=soft)
  File "/home/odoo/src/enterprise/account_asset/models/account_move.py", line 109, in _post
    posted = super()._post(soft)
  File "/home/odoo/src/odoo/addons/sale/models/account_move.py", line 99, in _post
    posted = super()._post(soft)
  File "/home/odoo/src/enterprise/account_reports/models/account_move.py", line 48, in _post
    return super()._post(soft)
  File "/home/odoo/src/enterprise/account_avatax/models/account_move.py", line 15, in _post
    res = super()._post(soft=soft)
  File "/home/odoo/src/enterprise/account_invoice_extract/models/account_invoice.py", line 262, in _post
    posted = super()._post(soft)
  File "/home/odoo/src/enterprise/account_inter_company_rules/models/account_move.py", line 14, in _post
    posted = super()._post(soft)
  File "/home/odoo/src/enterprise/account_external_tax/models/account_move.py", line 53, in _post
    return super()._post(soft=soft)
  File "/home/odoo/src/enterprise/account_accountant/models/account_move.py", line 68, in _post
    posted = super()._post(soft)
  File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 3876, in _post
    draft_reverse_moves.reversed_entry_id._reconcile_reversed_moves(draft_reverse_moves, self._context.get('move_reverse_cancel', False))
  File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 3694, in _reconcile_reversed_moves
    lines.with_context(move_reverse_cancel=move_reverse_cancel).reconcile()
  File "/home/odoo/src/odoo/addons/account/models/account_move_line.py", line 2935, in reconcile
    return self._reconcile_plan([self])
  File "/home/odoo/src/odoo/addons/account/models/account_move_line.py", line 2345, in _reconcile_plan
    self._reconcile_plan_with_sync(plan_list, all_amls)
  File "/home/odoo/src/odoo/addons/account/models/account_move_line.py", line 2492, in _reconcile_plan_with_sync
    exchange_diff_values = exchange_lines_to_fix._prepare_exchange_difference_move_vals(
  File "/home/odoo/src/odoo/addons/account/models/account_move_line.py", line 2603, in _prepare_exchange_difference_move_vals
    accounting_exchange_date = journal.with_context(move_date=exchange_date).accounting_date
  File "/home/odoo/src/odoo/odoo/fields.py", line 1207, in __get__
    self.compute_value(recs)
  File "/home/odoo/src/odoo/odoo/fields.py", line 1389, in compute_value
    records._compute_field_value(self)
  File "/home/odoo/src/odoo/addons/mail/models/mail_thread.py", line 424, in _compute_field_value
    return super()._compute_field_value(field)
  File "/home/odoo/src/odoo/odoo/models.py", line 4867, in _compute_field_value
    fields.determine(field.compute, self)
  File "/home/odoo/src/odoo/odoo/fields.py", line 102, in determine
    return needle(*args)
  File "/home/odoo/src/odoo/addons/account/models/account_journal.py", line 366, in _compute_accounting_date
    journal.accounting_date = temp_move._get_accounting_date(move_date, has_tax)
  File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 4358, in _get_accounting_date
    lock_dates = self._get_violated_lock_dates(invoice_date, has_tax)
  File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 4389, in _get_violated_lock_dates
    return self.company_id._get_violated_lock_dates(invoice_date, has_tax)
  File "/home/odoo/src/odoo/addons/account/models/company.py", line 369, in _get_violated_lock_dates
    self.ensure_one()
  File "/home/odoo/src/odoo/odoo/models.py", line 5844, in ensure_one
    raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.company()

Обновлять: Я добавил компанию, использующую with_company(), в метод подтверждения, и это устранило проблему.

refundInvoice.with_company(invoice.company_id).action_post()

У меня много вопросов: Какая версия Odoo? Какой пользователь входит в систему при использовании API? Активирована ли функция работы с несколькими компаниями?

CZoellner 12.03.2024 13:49

Я использую odoo17, активировано несколько компаний, и я не уверен, что вы подразумеваете под пользователем, вошедшим в систему. Я использую пользовательскую авторизацию, которая использует собственный ключ API пользователя, чтобы убедиться, что он является пользователем в системе. Я добавил код для пользовательской авторизации, а также http.route.

Brandon Huynh 13.03.2024 08:03

Ладно, я слепой, не увидел первую строку кода. Хм, я не разбираюсь в том, как контекст или среда строятся на основе этих вызовов, но я думаю, что чего-то не хватает в вашей пользовательской аутентификации, когда вы устанавливаете пользователя для env. Активен ли пользователь в компании? И когда да, в какой компании? Тот, который ему нужен для выставления счетов/возвратов?

CZoellner 13.03.2024 09:12

Да, я вхожу в систему под нужным пользователем, и у него есть доступ ко всем компаниям. Я создал другие API, которые создают записи в моделях sale.order и account.move и подтверждают их с помощью метода action_post(). Только когда я переворачиваю его и пытаюсь подтвердить обратное, я получаю эту ошибку.

Brandon Huynh 13.03.2024 17:57
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
148
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете выполнить отладку ниже строки:

File "/home/odoo/src/odoo/addons/account/models/account_move.py", line 4389, in _get_violated_lock_dates
    return self.company_id._get_violated_lock_dates(invoice_date, has_tax)

и проверь, что приходит self.company_id и self._context

  • В self.company должно быть 0 или более 1 записей о компаниях.
  • Поэтому, когда он вызывает метод _get_violated_lock_dates, он предполагает, что у него есть один Company_id, и продолжает работу.
  • Попробуйте проверить, откуда этот идентификатор self.company не получает точное значение 1.

Хорошо, я понял это. Поскольку запись о компании отсутствует, я передал компанию, указанную в счете, с помощью returnInvoice.with_company(invoice.company_id).action_post() при подтверждении обратной записи.

Brandon Huynh 14.03.2024 14:57

Большой ! иногда это можно решить, добавив контекст, например: self.env['account.pay'].sudo().with_context(default_comp‌any_id=user_rec.comp‌any_id.id).create(pa‌​yment_order_vals)

Vinay Davda 15.03.2024 06:18

Другие вопросы по теме

Похожие вопросы