装饰器(跨领域调用时增强异常信息)

  1. 装饰器
python 复制代码
from functools import wraps
import traceback
from odoo import _
from odoo.exceptions import ValidationError
from odoo.http import request

LAST_ITEM_INDEX = -1  # 列表中最后一个元素
# 领域翻译
IR_DOMAIN_TRANSLATE = {
    'fin': _('fin'),  # 财务会计
    'mfg': _('mfg'),  # 生产制造
    'ext': _('ext'),  # 外部系统管理
}


def wrap_module_exceptions(func):
    """
    装饰器:自动为来自其他领域的异常添加路径信息
    
    当异常发生在指定领域(如ext)时,自动在异常消息前添加领域名称前缀。
    主要用于跨领域调用时的异常信息增强。
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            # 提取堆栈信息 traceback.FrameSummary列表
            tb_list = traceback.extract_tb(e.__traceback__)
            if not tb_list:
                raise
            # 获取异常最后一帧
            last_frame = tb_list[LAST_ITEM_INDEX]
            
            # 构建新消息
            new_msg = e.args[0] if e.args else str(e)
            # 指定领域
            origin_names = ['ext', 'tax', 'scm', 'cost']
            for origin_name in origin_names:
                name = IR_DOMAIN_TRANSLATE.get(origin_name, '')
                if name and origin_name in last_frame.filename:
                    new_msg = f"[{name}] {new_msg}"
                    break
            
            if isinstance(e, ValidationError):
                # 保留原始异常链
                raise ValidationError(new_msg) from e
            else:
                # 修改异常消息,保持异常对象
                if e.args:
                    e.args = (new_msg,) + e.args[1:]
                else:
                    e = new_msg
            
            # 抛出异常
            raise
    return wrapper
  1. 应用
python 复制代码
from odoo.addons.ps_fin_doc_base.models.exception_handler import wrap_module_exceptions

@wrap_module_exceptions
def hook_after_audit_update(self, *args, **kwargs):
    pass
  1. 日志对比
  • 应用前
python 复制代码
odoo.addons.ps_studio.models.handler.service_handler: ('财务应付日期不能早于暂估应付日期', None) 
Traceback (most recent call last):
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 538, in _studio_call_services
    service_result = self._deal_after_service(preset_data, single_record, default_opt_msg)
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 716, in _deal_after_service
    all_svc_config = preset_data["after_services"].filtered(lambda svc: 'std_pre_svc_unlock' not in svc.svc_method))
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 1092, in p_call_services
    svc_res = self._call_odoo_service(model_key, operation, origin_args, timing, single_record, svc_config)
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 1141, in _call_odoo_service
    args = args)
    ####
  File "/opt/projects/insuite/biz/fin/ps_ap/ap_payable/development/models/ap_payable.py", line 1918, in hook_after_audit_update
    self._event("on_ap_payable_listen_target_doc_audit").notify(self,source_model_key,record,source_doc)
  File "/opt/projects/insuite/biz/third-party/OCA-connector/component_event/components/event.py", line 191, in notify
    event(*args, **kwargs)
  File "/opt/projects/insuite/biz/third-party/OCA-connector/component_event/components/event.py", line 160, in func_wrapper
    return func(*args, **kwargs)
  File "/opt/projects/insuite/biz/scm/ps_stk/stk_pur_receipt/development/models/stk_pur_receipt.py", line 3964, in on_ap_payable_listen_target_doc_audit
    self.env['ia.in.result'].update_realcost(tar_docs=tar_docs,is_audit=True,is_return=False)
  File "/opt/projects/insuite/biz/cost/ps_ia/ia_pub/models/ia_in_result.py", line 303, in update_realcost
    raise ValidationError(_('The financial payable date cannot be earlier than the estimated payable date'))
    ####
odoo.exceptions.ValidationError: ('财务应付日期不能早于暂估应付日期', None)
  • 应用后
python 复制代码
odoo.addons.ps_studio.models.handler.service_handler: ('[成本模块] 财务应付日期不能早于暂估应付日期', None) 
Traceback (most recent call last):
  File "/opt/projects/insuite/biz/fin/ps_ap/ap_payable/development/models/ap_payable.py", line 64, in wrapper
    return func(*args, **kwargs)
  File "/opt/projects/insuite/biz/fin/ps_ap/ap_payable/development/models/ap_payable.py", line 1918, in hook_after_audit_update
    self._event("on_ap_payable_listen_target_doc_audit").notify(self,source_model_key,record,source_doc)
  File "/opt/projects/insuite/biz/third-party/OCA-connector/component_event/components/event.py", line 191, in notify
    event(*args, **kwargs)
  File "/opt/projects/insuite/biz/third-party/OCA-connector/component_event/components/event.py", line 160, in func_wrapper
    return func(*args, **kwargs)
  File "/opt/projects/insuite/biz/scm/ps_stk/stk_pur_receipt/development/models/stk_pur_receipt.py", line 3964, in on_ap_payable_listen_target_doc_audit
    self.env['ia.in.result'].update_realcost(tar_docs=tar_docs,is_audit=True,is_return=False)
  File "/opt/projects/insuite/biz/cost/ps_ia/ia_pub/models/ia_in_result.py", line 303, in update_realcost
    raise ValidationError(_('The financial payable date cannot be earlier than the estimated payable date'))
odoo.exceptions.ValidationError: ('财务应付日期不能早于暂估应付日期', None)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 538, in _studio_call_services
    service_result = self._deal_after_service(preset_data, single_record, default_opt_msg)
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 716, in _deal_after_service
    all_svc_config = preset_data["after_services"].filtered(lambda svc: 'std_pre_svc_unlock' not in svc.svc_method))
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 1092, in p_call_services
    svc_res = self._call_odoo_service(model_key, operation, origin_args, timing, single_record, svc_config)
  File "/opt/projects/insuite/biz/platform/ps_studio/models/handler/service_handler.py", line 1141, in _call_odoo_service
    args = args)
  File "/opt/projects/insuite/biz/fin/ps_ap/ap_payable/development/models/ap_payable.py", line 77, in wrapper
    raise ValidationError(new_msg) from e
odoo.exceptions.ValidationError: ('[成本模块] 财务应付日期不能早于暂估应付日期', None)
相关推荐
Bruce_Liuxiaowei1 小时前
Python 实例赋值遮蔽类属性:一个从不报错的静默陷阱
开发语言·python·语法糖
做运维的阿瑞1 小时前
Python 标准库汇总:分类速览与常用模块清单
linux·运维·python
why-geo1 小时前
Hermes Agent 与 Python 的会产生什么样的碰撞
人工智能·python·ai编程
正经教主1 小时前
【FDE系列】阶段2:Day 29:FastAPI 进阶 — Pydantic 模型与完整 CRUD 实战
人工智能·python·fde
gCode Teacher 格码致知1 小时前
Pandas教学-6:coerce详解
python·pandas
梦在远山后1 小时前
Electron 与 FastAPI 如何完成流式 Agent 对话
python·langchain·agent
大衛說1 小时前
12 · 文件 I/O 与序列化
python
小静AI工程实验室2 小时前
Python 爬虫中文乱码排查:严格解码、UTF-8 BOM 与 JSON 转义的 12 项实验
字符编码·爬虫·python
天天被压力2 小时前
【跨市场数据实战 #08】可转债折价机会怎么筛:3个接口抓比价、列表和实时盘口
java·人工智能·python
weixin199701080162 小时前
[特殊字符]️《从0到1搭多平台二手ERP中台:闲鱼+淘宝+京东+拼多多+Mercari统一调度》(附Python源码)
python