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

Odoo 15调度器无法自动运行及手动执行失效求助

Odoo 15 Cron调度器无法运行问题排查与解决

问题描述

用于发送聊天消息的Python函数通过自定义按钮可正常执行,但配置的Cron调度器既无法自动运行,手动点击「Run Manually」也无反应。

原Python函数代码

def action_send_notification(self):
    today_date = datetime.today()
    for i in self:
        if i.search([('date_end','<',today_date)]):
            message = "STR has been expired"
            recipient1 = i.employee_id.user_id.partner_id.id
            recipient2 = i.env['res.users'].sudo().search([('name', 'ilike', 'admin')])                              
            channel = i.env['mail.channel'].channel_get([recipient1])
            channel_id = i.env['mail.channel'].browse(channel["id"])
            channel_id.message_post(    
               body=message,
               message_type='comment',
               subtype_xmlid='mail.mt_comment',)            

原Cron XML配置

<record id="STR_notif_expiration_scheduler" model="ir.cron">
    <field name="name">STR Notif Expiration</field>
    <field name="user_id" ref="base.user_root" />
    <field name="interval_number">1</field>
    <field name="interval_type">minutes</field>
    <field name="numbercall">-1</field>
    <field name="doall">0</field>
    <field name="model_id" ref="model_hr_str"/>
    <field name="code">model.action_send_notification()</field>
    <field name="priority">5</field>
</record>

核心问题分析

  1. 方法上下文不匹配:按钮点击时,self是当前表单/选中的hr.str记录集;但Cron调用model.action_send_notification()时,self是空记录集,导致for i in self循环直接跳过,代码完全未执行。
  2. 逻辑错误:i.search([('date_end','<',today_date)])是用单条记录去搜索符合条件的记录,而非在模型级别筛选所有过期记录,逻辑冗余且不符合Cron批量处理的需求。
  3. 潜在时区问题:datetime.today()使用本地时间,与Odoo存储的UTC时间可能存在偏差,导致过期判断不准确。

修复方案

1. 修改Python函数为模型级批量处理方法

调整逻辑,直接筛选所有过期记录并处理,同时修正时区问题、添加异常跳过逻辑:

from datetime import datetime
from odoo import models, fields, api
import logging

_logger = logging.getLogger(__name__)

class HrSTR(models.Model):
    _name = 'hr.str'
    # 原有字段定义...

    def action_send_notification(self):
        _logger.info("STR过期通知Cron开始执行")
        # 使用Odoo内置工具获取带时区的当前时间
        today_date = fields.Datetime.now()
        # 批量搜索所有过期的STR记录
        expired_records = self.search([('date_end', '<', today_date)])
        
        # 获取admin用户(添加limit=1避免匹配多个结果)
        admin_user = self.env['res.users'].sudo().search([('name', 'ilike', 'admin')], limit=1)
        if not admin_user:
            _logger.warning("未找到name包含admin的用户,终止通知发送")
            return
        
        for str_rec in expired_records:
            # 检查员工是否关联用户
            recipient_partner = str_rec.employee_id.user_id.partner_id
            if not recipient_partner:
                _logger.warning(f"STR记录{str_rec.id}的员工未关联用户,跳过通知")
                continue
            
            # 创建包含员工和admin的聊天频道
            channel_data = self.env['mail.channel'].channel_get([recipient_partner.id, admin_user.partner_id.id])
            channel = self.env['mail.channel'].browse(channel_data["id"])
            # 发送消息
            channel.message_post(    
                body="STR has been expired",
                message_type='comment',
                subtype_xmlid='mail.mt_comment',
            )
        _logger.info(f"STR过期通知Cron执行完成,共处理{len(expired_records)}条记录")

2. 验证Cron配置正确性

  • 确认model_id引用正确:进入设置 > 技术 > 数据库结构 > 模型,找到hr.str模型,查看其外部ID是否为model_hr_str,若不符需修改XML中的ref值。
  • 检查Cron状态:打开Cron记录(设置 > 技术 > 自动化 > 计划动作),确保「Active」选项已勾选。
  • 权限确认:user_id使用base.user_root(超级用户),权限足够执行所有操作,无需调整。

3. 调试与验证

  • 查看日志:执行Cron后,进入设置 > 技术 > 日志 > 日志,搜索STR过期通知相关日志,确认方法是否被调用、是否有报错信息。
  • 手动测试:更新模块后,点击Cron的「Run Manually」,检查对应员工和admin的聊天窗口是否收到通知。

内容的提问来源于stack exchange,提问作者Satrio Lantip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:34:55