You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo中出现无法适配'NewId'类型错误,求解决方案

Odoo:编辑/删除行触发「无法适配'NewId'类型」错误及计算字段值随依赖项变动问题

原问题描述

编辑或删除销售订单行时,触发「无法适配'NewId'类型」错误,原实现代码如下:

@api.multi
@api.depends('product_id','order_id')
def _get_cost_price_currency_update2(self):
    for record in self:
        param2 =()
        query2 = '''SELECT hpp_update,cost_price_set_lock
                        FROM sale_order_line
                        WHERE order_id = %s AND product_id = %s
                 '''
        param2 +=(record.order_id.id,record.product_id.id)
        self.env.cr.execute(query2,param2)
        query_result_lines2= self.env.cr.dictfetchall()

        for line in query_result_lines2:
            if line['hpp_update']:
                cost_price_set_update = line['hpp_update']
            else:
                cost_price_set_update = line['cost_price_set_lock']
            record.cost_price_set_update = cost_price_set_update

cost_price_set_update = fields.Float(string='CPP Update', compute=_get_cost_price_currency_update2)

更新后问题

修改代码改用ORM查询后,新问题出现:cost_price_set_update的值始终随cost_price_set_lock的计算结果变动,无法保留首次存储的值。修改后的代码:

cost_price_set_lock = fields.Float(string='CPP Lock',compute=_get_cost_price_currency, store=True) 

@api.depends('order_id')
def _get_cost_price_currency_update2(self):
    cost_price_set_update2 = ''
    invoice_pool = self.env['sale.order.line']
    for record2 in self:
        for invoice in invoice_pool.search([('order_id', '=', record2.order_id.id), ('product_id', '=', record2.product_id.id)]):
            if invoice.hpp_update:
                cost_price_set_update2 = invoice.hpp_update
            else:
                cost_price_set_update2 = invoice.cost_price_set_lock
        record2.cost_price_set_update = cost_price_set_update2

cost_price_set_update = fields.Float(string='CPP Update', compute=_get_cost_price_currency_update2)

问题根源与修复方案

1. 「无法适配'NewId'类型」错误原因

原代码直接使用原生SQL查询时,未处理Odoo中新建未保存记录的临时ID(NewId)。新建记录会被分配形如__export__.xxxx的临时ID,直接传入SQL查询无法映射到数据库真实ID,从而触发类型错误。

2. 原错误修复代码

改用Odoo ORM查询替代原生SQL,ORM会自动处理临时ID的映射逻辑:

@api.depends('product_id', 'order_id')
def _get_cost_price_currency_update2(self):
    for record in self:
        # ORM查询自动处理NewId映射
        lines = self.env['sale.order.line'].search([
            ('order_id', '=', record.order_id.id),
            ('product_id', '=', record.product_id.id)
        ])
        # 明确取第一条匹配记录的值(需根据业务调整多条记录的处理逻辑)
        if lines:
            line = lines[0]
            record.cost_price_set_update = line.hpp_update or line.cost_price_set_lock
        else:
            record.cost_price_set_update = 0.0

cost_price_set_update = fields.Float(string='CPP Update', compute=_get_cost_price_currency_update2)

3. 「值随cost_price_set_lock变动」问题修复

当前cost_price_set_update是非存储型计算字段,每次依赖项变动都会重新计算。若要保留首次计算的值,需将字段改为存储型计算字段,并控制仅在特定条件下更新:

cost_price_set_update = fields.Float(
    string='CPP Update', 
    compute=_get_cost_price_currency_update2,
    store=True,  # 开启字段存储
    readonly=True  # 禁止手动修改
)

@api.depends('product_id', 'order_id', 'cost_price_set_lock')
def _get_cost_price_currency_update2(self):
    for record in self:
        # 仅当字段未设置时更新,保留首次计算的值
        if not record.cost_price_set_update:
            lines = self.env['sale.order.line'].search([
                ('order_id', '=', record.order_id.id),
                ('product_id', '=', record.product_id.id)
            ])
            if lines:
                line = lines[0]
                record.cost_price_set_update = line.hpp_update or line.cost_price_set_lock
            else:
                record.cost_price_set_update = 0.0

额外注意事项

  • 若hpp_update或cost_price_set_lock可能为空,需设置默认值(如0.0)避免类型错误
  • 当查询多条sale.order.line时,需明确取值逻辑(如取第一条、最新创建的记录),避免循环覆盖值

内容的提问来源于stack exchange,提问作者Nur Faiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:15:20