Hello All
I try to access the field "invoice_ids" on the model sale.order with OdooRPC. It does not work, it shows the error below. I can access other Many2Many fields, for example tag_ids without problems. I can access the field invoice_ids from Odoo itself, also with code, but not with OdooRPC. What could be the problem? Thank you!
CODE:
for order in SaleOrder.browse(SaleOrder_ids):
print (order.invoice_ids)
ERROR:ERROR: {'code': 200, 'message': 'Odoo Server Error', 'data': {'name': 'builtins.TypeError', 'debug': 'Traceback (most recent call last):\n File "/home/odoo/src/odoo/odoo/http.py", line 1584, in _serve_db\n return service_model.retrying(self._serve_ir_http, self.env)\n File "/home/odoo/src/odoo/odoo/service/model.py", line 133, in retrying\n result = func()\n File "/home/odoo/src/odoo/odoo/http.py", line 1611, in _serve_ir_http\n response = self.dispatcher.dispatch(rule.endpoint, args)\n File "/home/odoo/src/odoo/odoo/http.py", line 1818, in dispatch\n return self._response(result)\n File "/home/odoo/src/odoo/odoo/http.py", line 1854, in _response\n return self.request.make_json_response(response)\n File "/home/odoo/src/odoo/odoo/http.py", line 1438, in make_json_response\n data = json.dumps(data, ensure_ascii=False, default=date_utils.json_default)\n File "/usr/lib/python3.10/json/__init__.py", line 238, in dumps\n **kw).encode(obj)\n File "/usr/lib/python3.10/json/encoder.py", line 199, in encode\n chunks = self.iterencode(o, _one_shot=True)\n File "/usr/lib/python3.10/json/encoder.py", line 257, in iterencode\n return _iterencode(o, 0)\nTypeError: keys must be str, int, float, bool or None, not frozendict\n', 'message': 'keys must be str, int, float, bool or None, not frozendict', 'context': {}, 'arguments': ['keys must be str, int, float, bool or None, not frozendict']}}Traceback (most recent call last):File "main.py", line 25, inprint (order.invoice_ids)File "/home/pi/.local/lib/python3.5/site-packages/odoorpc/fields.py", line 415, in __get__env, ids, from_record=(instance, self))File "/home/pi/.local/lib/python3.5/site-packages/odoorpc/models.py", line 246, in _browserecords._init_values()File "/home/pi/.local/lib/python3.5/site-packages/odoorpc/models.py", line 361, in _init_valuesself.ids, basic_fields, context=context, load='_classic_write')File "/home/pi/.local/lib/python3.5/site-packages/odoorpc/models.py", line 74, in rpc_methodcls._name, method, args, kwargs)File "/home/pi/.local/lib/python3.5/site-packages/odoorpc/odoo.py", line 486, in execute_kw'args': args_to_send})File "/home/pi/.local/lib/python3.5/site-packages/odoorpc/odoo.py", line 285, in jsondata['error'])odoorpc.error.RPCError: keys must be str, int, float, bool or None, not frozendict
Dear Jort
Thanks for your fast response. I already tried your approach, and now tried again, but with the same result. It gives me exactly the same error.
Best regards
Apologies, I was too hasty in answering your question. Looking at the source code for Odoo 15 I noticed that the invoice_ids is a computed value, and as such, it is not stored in the database. You should be able to access it with something like below, which is taken from the source code of the sale.order model:
@api.depends('order_line.invoice_lines')
def _get_invoiced(self):
# The invoice_ids are obtained thanks to the invoice lines of the SO
# lines, and we also search for possible refunds created directly from
# existing invoices. This is necessary since such a refund is not
# directly linked to the SO.
for order in self:
invoices = order.order_line.invoice_lines.move_id.filtered(lambda r: r.move_type in ('out_invoice', 'out_refund'))
order.invoice_ids = invoices
order.invoice_count = len(invoices)
So `order.order_line.invoice_lines.move_id.filtered(lambda r: r.move_type in ('out_invoice', 'out_refund'))` should return the invoice ids.
For OdooRPC this could look something like this:
ids = [1,2]
result_dict = {}
sale_orders = env.execute(
'sale.order',
'search_read',
[],
{
'domain': [('id', 'in', ids)],
'fields': ['id'],
}
)
for sale_order in sale_orders:
sale_order_lines = env.execute(
'sale.order.line',
'search_read',
[],
{
'domain': [('order_id', '=', sale_order['id'])],
'fields': ['invoice_lines'],
}
)
invoice_ids = []
for sale_order_line in sale_order_lines:
for invoice_line in sale_order_line['invoice_lines']:
move_lines = env.execute(
'account.move.line',
'search_read',
[],
{
'domain': [('id', '=', invoice_line)],
'fields': ['move_id'],
}
)
for move_line in move_lines:
if move_line['move_id']:
invoice_id = env.execute(
'account.move',
'search_read',
[],
{
'domain': [('id', '=', move_line['move_id'][0])],
'fields': ['move_type'],
}
)[-1]
if invoice_id['move_type'] in ['out_invoice', 'out_refund']:
invoice_ids.append(invoice_id['id'])
result_dict[sale_order['id']] = invoice_ids
print(result_dict)
You should probably change some parts to fit your requirements, and perhaps make it more efficient (i.e., less loops).