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

Odoo如何跨函数更新payrun_chatter_log创建记录的body字段

问题说明

在custom_button函数中更新payrun_chatter_log()方法创建的mail.message记录的body字段时更新失败,原有实现代码如下:

def payrun_chatter_log(self):
        subtype = self.env['mail.message.subtype'].search([('id','=', '2')])
    
        vals = {
            'date': fields.datetime.now(),
            'email_from': self.env.user.email_formatted,
            'author_id': self.env.user.id,
            'message_type': 'notification',
            'subtype_id': subtype.id,
            'is_internal': True,
            'model': 'custom.module',
            'res_id': self.id,
            'body': 'Test'
        }
        self.env['mail.message'].create(vals)
    
def custom_button(self):
        chatter = self.env['mail.message'].search([('res_id', '=', self.id)])
        message = 'Custom Message here'
        chatter.update({'body': message})
        return super(CustomModule, self).custom_button()
失败原因
  • 搜索条件仅匹配res_id,会拉取当前单据下所有消息记录,包含系统生成的、当前用户无编辑权限的记录,批量更新时会被ORM权限规则拦截,导致整体操作失败。
  • mail.message模型默认有严格的写入权限控制,普通用户仅能编辑自身创建的、在允许编辑时间窗口内的消息,非管理员/非作者直接修改历史消息会被拦截。
  • 创建消息时未保存返回的消息实例ID,后续更新无法精准定位目标记录,容易匹配到非目标消息。
修复方案
  1. 创建日志消息时保存返回的消息ID,优先通过关联字段绑定到当前单据,避免后续搜索匹配错误。
  2. 搜索目标消息时补全过滤条件,精准定位到自己创建的目标日志,不要全量拉取所有关联消息。
  3. 对目标单条记录使用提权操作绕过权限拦截,禁止对不确定范围的记录集批量提权修改。

修复后参考代码:

from odoo import fields, models

class CustomModule(models.Model):
    _name = 'custom.module'
    # 新增字段存储创建的日志消息ID,方便后续精准定位
    payrun_log_message_id = fields.Many2one('mail.message', string='薪资运行日志消息')

    def payrun_chatter_log(self):
        # 主键查询直接用browse,比search效率更高,ID=2是Odoo内置的讨论子类型,固定存在
        subtype = self.env['mail.message.subtype'].browse(2)
        vals = {
            'date': fields.datetime.now(),
            'email_from': self.env.user.email_formatted,
            'author_id': self.env.user.id,
            'message_type': 'notification',
            'subtype_id': subtype.id,
            'is_internal': True,
            'model': 'custom.module',
            'res_id': self.id,
            'body': 'Test'
        }
        # 保存创建的消息记录到关联字段
        self.payrun_log_message_id = self.env['mail.message'].create(vals)
    
    def custom_button(self):
        new_message_content = 'Custom Message here'
        # 直接通过关联字段定位目标消息,提权后更新
        if self.payrun_log_message_id:
            self.payrun_log_message_id.sudo().write({'body': new_message_content})

        # 不想新增字段的话,搜索时补全所有过滤条件精准匹配目标记录
        # target_log = self.env['mail.message'].search([
        #     ('model', '=', 'custom.module'),
        #     ('res_id', '=', self.id),
        #     ('author_id', '=', self.env.user.id),
        #     ('is_internal', '=', True),
        #     ('message_type', '=', 'notification'),
        #     ('body', '=', 'Test')
        # ], limit=1)
        # if target_log:
        #     target_log.sudo().write({'body': new_message_content})

        return super(CustomModule, self).custom_button()
补充说明
  • Odoo 16及以上版本对mail.message增加了额外的防篡改校验,修改历史消息必须使用sudo()提权才能正常写入。
  • 提权操作仅针对确定的单条目标记录执行,避免扩大权限范围误改系统其他消息数据。

内容的提问来源于stack exchange,提问作者Kai Ning

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:51:21