提交 647974dd authored 作者: 贺阳's avatar 贺阳

倒序和漏推优化

上级 2c0fb2dc
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging import logging
import re import re
from datetime import datetime, timedelta from datetime import timedelta
from odoo import models, fields, api, _
from odoo import models, fields, api
from odoo.exceptions import UserError from odoo.exceptions import UserError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
...@@ -23,15 +24,15 @@ class BlPatrol(models.Model): ...@@ -23,15 +24,15 @@ class BlPatrol(models.Model):
('done', '完成'), ('done', '完成'),
('failed', '失败') ('failed', '失败')
], string='状态', default='draft', required=True) ], string='状态', default='draft', required=True)
# 问题详情 # 问题详情
package_issues = fields.Text('小包轨迹问题') package_issues = fields.Text('小包轨迹问题')
bl_issues = fields.Text('提单关务节点问题') bl_issues = fields.Text('提单关务节点问题')
# 邮件发送记录 # 邮件发送记录
email_sent = fields.Boolean('邮件已发送', default=False) email_sent = fields.Boolean('邮件已发送', default=False)
email_sent_time = fields.Datetime('邮件发送时间') email_sent_time = fields.Datetime('邮件发送时间')
@api.model @api.model
def cron_bl_patrol(self): def cron_bl_patrol(self):
""" """
...@@ -44,10 +45,10 @@ class BlPatrol(models.Model): ...@@ -44,10 +45,10 @@ class BlPatrol(models.Model):
'check_date': fields.Date.today(), 'check_date': fields.Date.today(),
'state': 'running' 'state': 'running'
}) })
# 执行巡查 提单日期为近x天(默认5天),清关中和完成的提单 # 执行巡查 提单日期为近x天(默认5天),清关中和完成的提单
result = patrol._execute_patrol() result = patrol._execute_patrol()
# 更新巡查记录 # 更新巡查记录
patrol.write({ patrol.write({
'state': 'done' if result['success'] else 'failed', 'state': 'done' if result['success'] else 'failed',
...@@ -56,24 +57,17 @@ class BlPatrol(models.Model): ...@@ -56,24 +57,17 @@ class BlPatrol(models.Model):
'package_issues': result['package_issues'], 'package_issues': result['package_issues'],
'bl_issues': result['bl_issues'] 'bl_issues': result['bl_issues']
}) })
# 如果有问题,发送邮件 # 如果有问题,发送邮件
if result['issue_count'] > 0: if result['issue_count'] > 0:
patrol._send_patrol_email(result) patrol._send_patrol_email(result)
_logger.info(f"提单巡查完成: {patrol.name}, 发现问题: {result['issue_count']}") _logger.info(f"提单巡查完成: {patrol.name}, 发现问题: {result['issue_count']}")
except Exception as e: except Exception as e:
_logger.error(f"提单巡查失败: {str(e)}") _logger.error(f"提单巡查失败: {str(e)}")
# 如果有巡查记录,更新状态为失败
if 'patrol' in locals():
patrol.write({
'state': 'failed',
'package_issues': f"巡查执行失败: {str(e)}",
'bl_issues': f"巡查执行失败: {str(e)}"
})
raise UserError(f"巡查失败: {str(e)}") raise UserError(f"巡查失败: {str(e)}")
def _execute_patrol(self): def _execute_patrol(self):
""" """
执行巡查逻辑 执行巡查逻辑
...@@ -85,59 +79,59 @@ class BlPatrol(models.Model): ...@@ -85,59 +79,59 @@ class BlPatrol(models.Model):
""" """
# 获取配置 # 获取配置
config = self.env['ir.config_parameter'].sudo() config = self.env['ir.config_parameter'].sudo()
check_days = int(config.get_param('patrol_check_days', default=5))#巡查天数 check_days = int(config.get_param('patrol_check_days', default=5)) # 巡查天数
# 计算检查日期范围 # 计算检查日期范围
end_date = fields.Date.today() end_date = fields.Date.today()
start_date = end_date - timedelta(days=check_days) start_date = end_date - timedelta(days=check_days)
# 查找符合条件的提单 提单日期为近x天(默认5天),清关中和完成的提单。 # 查找符合条件的提单 提单日期为近x天(默认5天),清关中和完成的提单。
bls = self.env['cc.bl'].sudo().search([('bl_date', '>=', start_date),('bl_date', '<=', end_date),('state', 'in', ['ccing', 'done'])]) bls = self.env['cc.bl'].sudo().search(
[('bl_date', '>=', start_date), ('bl_date', '<=', end_date), ('state', 'in', ['ccing', 'done'])])
_logger.info(f"开始巡查提单,检查范围: {start_date} 到 {end_date}, 提单数量: {len(bls)}") _logger.info(f"开始巡查提单,检查范围: {start_date} 到 {end_date}, 提单数量: {len(bls)}")
package_issues = [] error_package_issues = []
bl_issues = [] error_bl_issues = []
global_issue_counter = 1 package_issue_counter = 1 # 小包问题独立编号
bl_issue_counter = 1 # 提单问题独立编号
for bl in bls: for bl in bls:
# 检查小包轨迹问题 # 检查小包轨迹问题
bl_package_issues = self._check_package_tracking_issues(bl) bl_package_issues = self._check_package_tracking_issues(bl)
if bl_package_issues: if bl_package_issues:
# 为小包问题添加全局编号 # 为小包问题添加独立编号
for i, issue in enumerate(bl_package_issues): for i, issue in enumerate(bl_package_issues):
# 使用正则表达式匹配任何数字+顿号的格式 # 使用正则表达式匹配任何数字+顿号的格式
if re.match(r'^\d+、', issue): if re.match(r'^\d+、', issue):
# 替换开头的编号 # 替换开头的编号
bl_package_issues[i] = re.sub(r'^\d+、', f"{global_issue_counter}、", issue, 1) bl_package_issues[i] = re.sub(r'^\d+、', f"{package_issue_counter}、", issue, 1)
else: else:
# 如果没有编号,添加编号 # 如果没有编号,添加编号
bl_package_issues[i] = f"{global_issue_counter}、{issue}" bl_package_issues[i] = f"{package_issue_counter}、{issue}"
global_issue_counter += 1 package_issue_counter += 1
package_issues.extend(bl_package_issues) error_package_issues.extend(bl_package_issues)
# 检查提单关务节点问题 # 检查提单关务节点问题
bl_node_issues = self._check_bl_node_issues(bl) bl_node_issues = self._check_bl_node_issues(bl)
if bl_node_issues: if bl_node_issues:
# 为提单问题添加全局编号 # 为提单问题添加独立编号
for i, issue in enumerate(bl_node_issues): for i, blissue in enumerate(bl_node_issues):
# 使用正则表达式匹配任何数字+顿号的格式 # 使用正则表达式匹配任何数字+顿号的格式
if re.match(r'^\d+、', issue): if re.match(r'^\d+、', blissue):
# 替换开头的编号 # 替换开头的编号
bl_node_issues[i] = re.sub(r'^\d+、', f"{global_issue_counter}、", issue, 1) bl_node_issues[i] = re.sub(r'^\d+、', f"{bl_issue_counter}、", blissue, 1)
else: else:
# 如果没有编号,添加编号 # 如果没有编号,添加编号
bl_node_issues[i] = f"{global_issue_counter}、{issue}" bl_node_issues[i] = f"{bl_issue_counter}、{blissue}"
global_issue_counter += 1 bl_issue_counter += 1
bl_issues.extend(bl_node_issues) error_bl_issues.extend(bl_node_issues)
return { return {
'success': True, 'success': True,
'bl_count': len(bls), 'bl_count': len(bls),
'issue_count': len(package_issues) + len(bl_issues), 'issue_count': len(error_package_issues) + len(error_bl_issues),
'package_issues': '\n'.join(package_issues) if package_issues else '', 'package_issues': '\n'.join(error_package_issues) if error_package_issues else '',
'bl_issues': '\n'.join(bl_issues) if bl_issues else '' 'bl_issues': '\n'.join(error_bl_issues) if error_bl_issues else ''
} }
def _check_package_tracking_issues(self, bl): def _check_package_tracking_issues(self, bl):
""" """
检查小包轨迹问题 检查小包轨迹问题 - 只检查真正的小包节点,不检查关务节点
""" """
issues = [] issues = []
# 按问题类型分组统计 # 按问题类型分组统计
...@@ -146,29 +140,32 @@ class BlPatrol(models.Model): ...@@ -146,29 +140,32 @@ class BlPatrol(models.Model):
# 获取该提单下所有小包的同步日志 # 获取该提单下所有小包的同步日志
ship_packages = bl.ship_package_ids ship_packages = bl.ship_package_ids
for package in ship_packages: for package in ship_packages:
sync_logs = package.sync_log_ids.sorted('operate_time') sync_logs = package.sync_log_ids # 小包日志
if len(sync_logs) < 2: # 检查多条日志的倒叙问题 - 只检查小包节点,不检查关务节点
continue if len(sync_logs) >= 2:
# 检查倒叙问题 for i in range(1, len(sync_logs)):
for i in range(1, len(sync_logs)): current_log = sync_logs[i] # 当前日志
current_log = sync_logs[i] previous_log = sync_logs[i - 1] # 前一个日志
previous_log = sync_logs[i-1] current_time = current_log.operate_time # 当前日志时间
if current_log.operate_time < previous_log.operate_time: previous_time = previous_log.operate_time # 前一个日志时间
try: if current_time and previous_time and current_time < previous_time:
progress_name = current_log.progress_name or "空" try:
process_code = current_log.process_code or "空" # 检查节点类型,只处理小包节点
issue_key = f"{progress_name}({process_code})倒叙" node = self.env['cc.node'].sudo().search(
if issue_key not in reverse_issues: [('node_type', '=', 'package'), ('tk_code', '=', current_log.process_code)])
reverse_issues[issue_key] = [] if node: # 只处理小包节点
reverse_issues[issue_key].append(package.logistic_order_no) progress_name = node.name or "空"
except Exception as e: process_code = node.tk_code or "空"
_logger.warning(f"构建小包倒叙问题描述失败: {str(e)}") issue_key = f"{progress_name}({process_code})倒叙"
issue_key = "节点倒叙" if issue_key not in reverse_issues:
if issue_key not in reverse_issues: reverse_issues[issue_key] = []
reverse_issues[issue_key] = [] reverse_issues[issue_key].append(package.logistic_order_no)
reverse_issues[issue_key].append(package.logistic_order_no) except Exception as e:
break _logger.warning(f"构建小包倒叙问题描述失败: {str(e)}")
# 检查漏推问题 - 根据节点配置检查 # 如果无法确定节点类型,跳过
continue
# 检查漏推问题 - 只检查小包节点
package_issues = self._check_package_missing_nodes(package, sync_logs) package_issues = self._check_package_missing_nodes(package, sync_logs)
for issue in package_issues: for issue in package_issues:
# 提取问题类型 # 提取问题类型
...@@ -180,7 +177,7 @@ class BlPatrol(models.Model): ...@@ -180,7 +177,7 @@ class BlPatrol(models.Model):
else: else:
# 如果格式不匹配,使用整个问题描述作为key # 如果格式不匹配,使用整个问题描述作为key
issue_key = issue issue_key = issue
if issue_key not in missing_issues: if issue_key not in missing_issues:
missing_issues[issue_key] = [] missing_issues[issue_key] = []
missing_issues[issue_key].append(package.logistic_order_no) missing_issues[issue_key].append(package.logistic_order_no)
...@@ -191,22 +188,24 @@ class BlPatrol(models.Model): ...@@ -191,22 +188,24 @@ class BlPatrol(models.Model):
if issue_key not in missing_issues: if issue_key not in missing_issues:
missing_issues[issue_key] = [] missing_issues[issue_key] = []
missing_issues[issue_key].append(package.logistic_order_no) missing_issues[issue_key].append(package.logistic_order_no)
# 格式化倒叙问题 # 格式化倒叙问题
issue_counter = 1 issue_counter = 1
for issue_type, packages in reverse_issues.items(): for issue_type, packages in reverse_issues.items():
package_list = self._format_package_list(packages) package_list = self._format_package_list(packages)
issues.append(f"{issue_counter}、{bl.bl_no},出现{issue_type},涉及小包{len(packages)},小包追踪号包括{package_list}") issues.append(
f"{issue_counter}、{bl.bl_no},出现{issue_type},涉及小包{len(packages)},小包追踪号包括{package_list}")
issue_counter += 1 issue_counter += 1
# 格式化漏推问题 # 格式化漏推问题
for issue_type, packages in missing_issues.items(): for issue_type, packages in missing_issues.items():
package_list = self._format_package_list(packages) package_list = self._format_package_list(packages)
issues.append(f"{issue_counter}、{bl.bl_no},出现{issue_type},涉及小包{len(packages)},小包追踪号包括{package_list}") issues.append(
f"{issue_counter}、{bl.bl_no},出现{issue_type},涉及小包{len(packages)},小包追踪号包括{package_list}")
issue_counter += 1 issue_counter += 1
return issues return issues
def _format_package_list(self, packages): def _format_package_list(self, packages):
""" """
格式化小包列表,最多显示10个 格式化小包列表,最多显示10个
...@@ -214,10 +213,8 @@ class BlPatrol(models.Model): ...@@ -214,10 +213,8 @@ class BlPatrol(models.Model):
try: try:
# 过滤掉None和空字符串 # 过滤掉None和空字符串
valid_packages = [pkg for pkg in packages if pkg and str(pkg).strip()] valid_packages = [pkg for pkg in packages if pkg and str(pkg).strip()]
if not valid_packages: if not valid_packages:
return "无有效追踪号" return "无有效追踪号"
if len(valid_packages) <= 10: if len(valid_packages) <= 10:
return "/".join(valid_packages) return "/".join(valid_packages)
else: else:
...@@ -225,39 +222,30 @@ class BlPatrol(models.Model): ...@@ -225,39 +222,30 @@ class BlPatrol(models.Model):
except Exception as e: except Exception as e:
_logger.warning(f"格式化小包列表失败: {str(e)}") _logger.warning(f"格式化小包列表失败: {str(e)}")
return "格式化失败" return "格式化失败"
def _check_package_missing_nodes(self, package, sync_logs): def _check_package_missing_nodes(self, package, sync_logs):
""" """
检查小包漏推节点 检查小包漏推节点
""" """
issues = [] issues = []
# 获取所有小包节点,按顺序排序 # 获取所有小包节点,按顺序排序
package_nodes = self.env['cc.node'].sudo().search([ package_nodes = self.env['cc.node'].sudo().search([('node_type', '=', 'package')], order='seq')
('node_type', '=', 'package')
], order='seq')
if not package_nodes: if not package_nodes:
return issues return issues
# 检查每个节点是否有对应的同步日志 # 检查每个节点是否有对应的同步日志
for node in package_nodes: for node in package_nodes:
# 跳过当前节点(最后一个节点) # 跳过当前节点(最后一个节点)
if node == package_nodes[-1]: if node == package_nodes[-1]:
continue continue
# 跳过初始节点(is_default=True) # 跳过初始节点(is_default=True)
if getattr(node, 'is_default', False): if getattr(node, 'is_default', False):
continue continue
# 检查是否有该节点的同步日志 # 检查是否有该节点的同步日志
has_node_log = any(log.process_code == node.tk_code for log in sync_logs) has_node_log = any(log.process_code == node.tk_code for log in sync_logs)
# 检查后续节点是否有日志 # 检查后续节点是否有日志
next_nodes = package_nodes.filtered(lambda n: n.seq > node.seq) next_nodes = package_nodes.filtered(lambda n: n.seq > node.seq)
for next_node in next_nodes: for next_node in next_nodes:
has_next_log = any(log.process_code == next_node.tk_code for log in sync_logs) has_next_log = any(log.process_code == next_node.tk_code for log in sync_logs)
# 如果后续节点有日志但当前节点没有,说明漏推 # 如果后续节点有日志但当前节点没有,说明漏推
if has_next_log and not has_node_log: if has_next_log and not has_node_log:
try: try:
...@@ -270,98 +258,92 @@ class BlPatrol(models.Model): ...@@ -270,98 +258,92 @@ class BlPatrol(models.Model):
_logger.warning(f"构建小包漏推问题描述失败: {str(e)}") _logger.warning(f"构建小包漏推问题描述失败: {str(e)}")
issues.append("节点轨迹漏推") issues.append("节点轨迹漏推")
break break
return issues return issues
def _check_bl_node_issues(self, bl): def _check_bl_node_issues(self, bl):
""" """
检查提单关务节点问题 检查提单关务节点问题
""" """
issues = [] issues = []
sync_logs = bl.bl_sync_log_ids # 提单日志
# 获取提单同步日志
sync_logs = bl.bl_sync_log_ids.sorted('operate_time')
if len(sync_logs) < 2:
return issues
# 检查倒叙问题 # 检查倒叙问题
issue_counter = 1 if len(sync_logs) >= 2:
for i in range(1, len(sync_logs)): _logger.info(f"=== 提单 {bl.bl_no} 倒序检查调试 ===")
current_log = sync_logs[i] # 获取所有提单节点,按业务顺序排序
previous_log = sync_logs[i-1] bl_nodes = self.env['cc.node'].sudo().search([('node_type', '=', 'bl')], order='seq')
if bl_nodes:
if current_log.operate_time < previous_log.operate_time: # 收集所有有日志的节点及其时间
try: node_logs = {} # {node_index: (node, log, time)}
progress_name = current_log.progress_name or "空" for i, node in enumerate(bl_nodes):
process_code = current_log.process_code or "空" for log in sync_logs:
issues.append( if log.process_code == node.tk_code:
f"{issue_counter}、{bl.bl_no},出现{progress_name}({process_code})倒叙" node_logs[i] = (node, log, log.operate_time)
) break
except Exception as e: # 遍历每个有日志的节点,与前面所有有日志的节点比较
_logger.warning(f"构建倒叙问题描述失败: {str(e)}") for current_idx in sorted(node_logs.keys()):
issues.append(f"{issue_counter}、{bl.bl_no},出现节点倒叙") current_node, current_log, current_time = node_logs[current_idx]
break # 与前面所有有日志的节点比较
for prev_idx in sorted(node_logs.keys()):
if prev_idx >= current_idx: # 跳过自己和自己后面的节点
continue
prev_node, prev_log, prev_time = node_logs[prev_idx]
# 检查时间顺序
if current_time and prev_time:
if current_time < prev_time:
try:
progress_name = current_log.progress_name or "空"
process_code = current_log.process_code or "空"
issues.append(
f"{bl.bl_no},出现{progress_name}({process_code})倒叙"
)
except Exception as e:
_logger.warning(f"构建倒序问题描述失败: {str(e)}")
issues.append(f"{bl.bl_no},出现节点倒叙")
# 检查漏推问题 # 检查漏推问题
bl_issues = self._check_bl_missing_nodes(bl, sync_logs) missing_issues = self._check_bl_missing_nodes(bl, sync_logs)
if bl_issues: if missing_issues:
# 为漏推问题添加编号 issues.extend(missing_issues)
for i, issue in enumerate(bl_issues, start=len(issues) + 1):
if issue.startswith("1."):
# 替换开头的编号
bl_issues[i-1] = issue.replace("1.", f"{i}、", 1)
issues.extend(bl_issues)
return issues return issues
def _check_bl_missing_nodes(self, bl, sync_logs): def _check_bl_missing_nodes(self, bl, sync_logs):
""" """
检查提单漏推节点 检查提单漏推节点
""" """
issues = [] issues = []
# 获取所有提单节点,按顺序排序 # 获取所有提单节点,按顺序排序
bl_nodes = self.env['cc.node'].sudo().search([ bl_nodes = self.env['cc.node'].sudo().search([('node_type', '=', 'bl')], order='seq')
('node_type', '=', 'bl')
], order='seq')
if not bl_nodes: if not bl_nodes:
return issues return issues
# 检查每个节点是否有对应的同步日志 # 检查每个节点是否有对应的同步日志
for node in bl_nodes: for node in bl_nodes:
# 跳过当前节点(最后一个节点) # 跳过当前节点(最后一个节点)
if node == bl_nodes[-1]: if node == bl_nodes[-1]:
continue continue
# 跳过初始节点(is_default=True) # 跳过初始节点(is_default=True)
if getattr(node, 'is_default', False): if getattr(node, 'is_default', False):
continue continue
# 检查是否有该节点的同步日志 # 检查是否有该节点的同步日志
has_node_log = any(log.process_code == node.tk_code for log in sync_logs) has_node_log = any(log.process_code == node.tk_code for log in sync_logs)
# 检查后续节点是否有日志 # 检查后续节点是否有日志
next_nodes = bl_nodes.filtered(lambda n: n.seq > node.seq) next_nodes = bl_nodes.filtered(lambda n: n.seq > node.seq)
for next_node in next_nodes: for next_node in next_nodes:
has_next_log = any(log.process_code == next_node.tk_code for log in sync_logs) has_next_log = any(log.process_code == next_node.tk_code for log in sync_logs)
# 如果后续节点有日志但当前节点没有,说明漏推 # 如果后续节点有日志但当前节点没有,说明漏推
if has_next_log and not has_node_log: if has_next_log and not has_node_log:
try: try:
node_name = node.name or "空" node_name = node.name or "空"
tk_code = node.tk_code or "空" tk_code = node.tk_code or "空"
issues.append( issues.append(
f"1.{bl.bl_no},出现{node_name}({tk_code})轨迹漏推" f"{bl.bl_no},出现{node_name}({tk_code})轨迹漏推"
) )
except Exception as e: except Exception as e:
_logger.warning(f"构建提单漏推问题描述失败: {str(e)}") _logger.warning(f"构建提单漏推问题描述失败: {str(e)}")
issues.append(f"1.{bl.bl_no},出现节点轨迹漏推") issues.append(f"{bl.bl_no},出现节点轨迹漏推")
break break
return issues return issues
def _send_patrol_email(self, result): def _send_patrol_email(self, result):
""" """
发送巡查邮件 发送巡查邮件
...@@ -371,21 +353,20 @@ class BlPatrol(models.Model): ...@@ -371,21 +353,20 @@ class BlPatrol(models.Model):
config = self.env['ir.config_parameter'].sudo() config = self.env['ir.config_parameter'].sudo()
receiver_emails = config.get_param('patrol_receiver_emails', default='') receiver_emails = config.get_param('patrol_receiver_emails', default='')
sender_email = config.get_param('patrol_sender_email', default='') sender_email = config.get_param('patrol_sender_email', default='')
if not receiver_emails or not sender_email: if not receiver_emails or not sender_email:
_logger.warning("邮件配置不完整,跳过邮件发送") _logger.warning("邮件配置不完整,跳过邮件发送")
return return
# 解析接收邮箱 # 解析接收邮箱
receiver_list = [email.strip() for email in receiver_emails.split('\n') if email.strip()] receiver_list = [email.strip() for email in receiver_emails.split('\n') if email.strip()]
# 构建邮件内容 # 构建邮件内容
subject = f"(重要)推送预警/{fields.Date.today()}系统巡查轨迹" subject = f"(重要)推送预警/{fields.Date.today()}系统巡查轨迹"
# 构建邮件内容 # 构建邮件内容
package_content = result['package_issues'] if result['package_issues'] else "无" package_content = result['package_issues'] if result['package_issues'] else "无"
bl_content = result['bl_issues'] if result['bl_issues'] else "无" bl_content = result['bl_issues'] if result['bl_issues'] else "无"
content = f"""您好,经系统巡查。 content = f"""您好,经系统巡查。
发现以下提单存在小包轨迹倒叙/轨迹漏推 发现以下提单存在小包轨迹倒叙/轨迹漏推
...@@ -395,7 +376,7 @@ class BlPatrol(models.Model): ...@@ -395,7 +376,7 @@ class BlPatrol(models.Model):
{bl_content} {bl_content}
请立即处理!!!""" 请立即处理!!!"""
# 发送邮件 # 发送邮件
self.env['mail.mail'].sudo().create({ self.env['mail.mail'].sudo().create({
'subject': subject, 'subject': subject,
...@@ -404,18 +385,18 @@ class BlPatrol(models.Model): ...@@ -404,18 +385,18 @@ class BlPatrol(models.Model):
'email_to': ','.join(receiver_list), 'email_to': ','.join(receiver_list),
'auto_delete': True, 'auto_delete': True,
}).send() }).send()
# 更新发送记录 # 更新发送记录
self.write({ self.write({
'email_sent': True, 'email_sent': True,
'email_sent_time': fields.Datetime.now() 'email_sent_time': fields.Datetime.now()
}) })
_logger.info(f"巡查邮件发送成功,接收人: {receiver_list}") _logger.info(f"巡查邮件发送成功,接收人: {receiver_list}")
except Exception as e: except Exception as e:
_logger.error(f"发送巡查邮件失败: {str(e)}") _logger.error(f"发送巡查邮件失败: {str(e)}")
def action_manual_patrol(self): def action_manual_patrol(self):
""" """
手动执行巡查 手动执行巡查
...@@ -423,7 +404,7 @@ class BlPatrol(models.Model): ...@@ -423,7 +404,7 @@ class BlPatrol(models.Model):
self.ensure_one() self.ensure_one()
if self.state != 'draft': if self.state != 'draft':
raise UserError('只能对草稿状态的巡查进行手动执行') raise UserError('只能对草稿状态的巡查进行手动执行')
self.cron_bl_patrol() self.cron_bl_patrol()
return { return {
'type': 'ir.actions.client', 'type': 'ir.actions.client',
...@@ -433,4 +414,4 @@ class BlPatrol(models.Model): ...@@ -433,4 +414,4 @@ class BlPatrol(models.Model):
'message': f'巡查已完成,发现问题: {self.issue_count}', 'message': f'巡查已完成,发现问题: {self.issue_count}',
'type': 'success', 'type': 'success',
} }
} }
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论