fix: 工单创建和飞书同步修复 + 日志精简
1. TSPAssistant.create_work_order 补齐 tenant_id 参数 2. workorder_sync._create_workorder 修复 SQLAlchemy session 泄漏(用 flush 替代 commit+refresh+expunge) 3. _find_existing_workorder 返回 order_id 字符串而非 ORM 对象 4. 飞书同步日志精简: - feishu_client API 请求/响应日志降为 DEBUG - flexible_field_mapper 字段映射日志降为 DEBUG - workorder_sync 字段转换日志降为 DEBUG - 只保留关键的创建/同步结果为 INFO
This commit is contained in:
@@ -82,11 +82,11 @@ class FeishuClient:
|
||||
kwargs['headers'] = headers
|
||||
|
||||
try:
|
||||
logger.info(f"发送飞书API请求: {method} {url}")
|
||||
logger.info(f"请求头: Authorization: Bearer {token[:20]}...")
|
||||
logger.debug(f"飞书API请求: {method} {url}")
|
||||
logger.debug(f"请求头: Authorization: Bearer {token[:20]}...")
|
||||
|
||||
response = requests.request(method, url, timeout=30, **kwargs)
|
||||
logger.info(f"飞书API响应状态码: {response.status_code}")
|
||||
logger.debug(f"飞书API响应状态码: {response.status_code}")
|
||||
|
||||
# 处理403权限错误
|
||||
if response.status_code == 403:
|
||||
@@ -100,7 +100,7 @@ class FeishuClient:
|
||||
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
logger.info(f"飞书API响应内容: {result}")
|
||||
logger.debug(f"飞书API响应内容: {str(result)[:200]}")
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"飞书API请求失败: {e}")
|
||||
|
||||
@@ -418,7 +418,7 @@ class FlexibleFieldMapper:
|
||||
'mapping_details': {}
|
||||
}
|
||||
|
||||
logger.info(f"开始转换字段: {list(feishu_fields.keys())}")
|
||||
logger.debug(f"开始转换字段: {list(feishu_fields.keys())}")
|
||||
|
||||
for feishu_field, value in feishu_fields.items():
|
||||
local_field = self.map_field(feishu_field)
|
||||
@@ -431,7 +431,7 @@ class FlexibleFieldMapper:
|
||||
'mapped': True,
|
||||
'value': value
|
||||
}
|
||||
logger.info(f"映射字段 {feishu_field} -> {local_field}: {value}")
|
||||
logger.debug(f"映射字段 {feishu_field} -> {local_field}: {str(value)[:50]}")
|
||||
else:
|
||||
conversion_stats['unmapped_fields'].append(feishu_field)
|
||||
conversion_stats['mapping_details'][feishu_field] = {
|
||||
@@ -441,7 +441,7 @@ class FlexibleFieldMapper:
|
||||
}
|
||||
logger.info(f"飞书字段 {feishu_field} 不存在于数据中")
|
||||
|
||||
logger.info(f"字段转换完成: 已映射 {conversion_stats['mapped_fields']}, "
|
||||
logger.debug(f"字段转换完成: 已映射 {conversion_stats['mapped_fields']}, "
|
||||
f"未映射 {len(conversion_stats['unmapped_fields'])}")
|
||||
|
||||
return local_data, conversion_stats
|
||||
|
||||
@@ -310,21 +310,21 @@ class WorkOrderSyncService:
|
||||
local_data = self._convert_feishu_to_local(fields)
|
||||
local_data["feishu_record_id"] = record_id
|
||||
|
||||
existing_workorder = self._find_existing_workorder(record_id)
|
||||
existing_order_id = self._find_existing_workorder(record_id)
|
||||
|
||||
if existing_workorder:
|
||||
if existing_order_id:
|
||||
return {
|
||||
"success": False,
|
||||
"message": f"工单已存在: {existing_workorder.order_id}"
|
||||
"message": f"工单已存在: {existing_order_id}"
|
||||
}
|
||||
|
||||
workorder = self._create_workorder(local_data)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"工单创建成功: {local_data.get('order_id')}",
|
||||
"workorder_id": workorder.id,
|
||||
"order_id": local_data.get('order_id')
|
||||
"message": f"工单创建成功: {workorder.get('order_id')}",
|
||||
"workorder_id": workorder.get('id'),
|
||||
"order_id": workorder.get('order_id')
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
@@ -334,45 +334,35 @@ class WorkOrderSyncService:
|
||||
"message": f"创建工单失败: {str(e)}"
|
||||
}
|
||||
|
||||
def _find_existing_workorder(self, feishu_record_id: str) -> Optional[WorkOrder]:
|
||||
"""查找已存在的工单"""
|
||||
def _find_existing_workorder(self, feishu_record_id: str) -> Optional[str]:
|
||||
"""查找已存在的工单,返回 order_id 或 None"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
return session.query(WorkOrder).filter(
|
||||
wo = session.query(WorkOrder.order_id).filter(
|
||||
WorkOrder.feishu_record_id == feishu_record_id
|
||||
).first()
|
||||
return wo[0] if wo else None
|
||||
except Exception as e:
|
||||
logger.error(f"查找现有工单失败: {e}")
|
||||
return None
|
||||
|
||||
def _create_workorder(self, local_data: Dict[str, Any]) -> WorkOrder:
|
||||
"""创建新工单"""
|
||||
def _create_workorder(self, local_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""创建新工单,返回 {id, order_id}"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
# 只使用WorkOrder模型支持的字段
|
||||
valid_data = {}
|
||||
for key, value in local_data.items():
|
||||
if hasattr(WorkOrder, key):
|
||||
# 确保值不是dict、list等复杂类型
|
||||
if isinstance(value, (dict, list)):
|
||||
logger.warning(f"字段 '{key}' 包含复杂类型 {type(value).__name__},跳过")
|
||||
continue
|
||||
valid_data[key] = value
|
||||
|
||||
workorder = WorkOrder(**valid_data)
|
||||
session.add(workorder)
|
||||
session.commit()
|
||||
session.refresh(workorder)
|
||||
|
||||
# 在session关闭前访问所有需要的属性,让SQLAlchemy加载它们
|
||||
workorder_id = workorder.id
|
||||
workorder_order_id = workorder.order_id
|
||||
|
||||
# 将对象从session中分离,这样它就不再依赖session
|
||||
session.expunge(workorder)
|
||||
|
||||
logger.info(f"创建工单成功: {workorder_order_id}")
|
||||
return workorder
|
||||
session.flush() # 获取 ID,不 commit(context manager 会 commit)
|
||||
result = {"id": workorder.id, "order_id": workorder.order_id}
|
||||
logger.info(f"创建工单成功: {result['order_id']}")
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"创建工单失败: {e}")
|
||||
raise
|
||||
@@ -428,11 +418,11 @@ class WorkOrderSyncService:
|
||||
|
||||
def _convert_feishu_to_local(self, feishu_fields: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""将飞书字段转换为本地工单字段"""
|
||||
logger.info(f"开始转换飞书字段: {feishu_fields}")
|
||||
logger.debug(f"开始转换飞书字段: {list(feishu_fields.keys())}")
|
||||
|
||||
local_data, conversion_stats = self.field_mapper.convert_fields(feishu_fields)
|
||||
|
||||
logger.info(f"字段转换统计: 总字段 {conversion_stats['total_fields']}, "
|
||||
logger.debug(f"字段转换统计: 总字段 {conversion_stats['total_fields']}, "
|
||||
f"已映射 {conversion_stats['mapped_fields']}, "
|
||||
f"未映射 {len(conversion_stats['unmapped_fields'])}")
|
||||
|
||||
|
||||
@@ -100,14 +100,15 @@ class TSPAssistant:
|
||||
self.logger.error(f"处理消息异常: {e}")
|
||||
return {"error": f"处理异常: {str(e)}"}
|
||||
|
||||
def create_work_order(self, title: str, description: str, category: str, priority: str = "medium") -> Dict[str, Any]:
|
||||
def create_work_order(self, title: str, description: str, category: str, priority: str = "medium", tenant_id: str = None) -> Dict[str, Any]:
|
||||
"""创建工单"""
|
||||
try:
|
||||
result = self.dialogue_manager.create_work_order(
|
||||
title=title,
|
||||
description=description,
|
||||
category=category,
|
||||
priority=priority
|
||||
priority=priority,
|
||||
tenant_id=tenant_id
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
|
||||
Reference in New Issue
Block a user