feat: 自动提交 - 周一 2025/09/22 11:24:32.93
This commit is contained in:
@@ -10,6 +10,7 @@ from typing import Dict, List, Optional, Any
|
||||
from datetime import datetime
|
||||
from src.integrations.feishu_client import FeishuClient
|
||||
from src.integrations.ai_suggestion_service import AISuggestionService
|
||||
from src.integrations.flexible_field_mapper import FlexibleFieldMapper
|
||||
from src.core.database import db_manager
|
||||
from src.core.models import WorkOrder
|
||||
# 工单状态和优先级枚举
|
||||
@@ -44,7 +45,10 @@ class WorkOrderSyncService:
|
||||
self.table_id = table_id
|
||||
self.ai_service = AISuggestionService()
|
||||
|
||||
# 字段映射配置 - 根据实际飞书表格结构
|
||||
# 初始化灵活字段映射器
|
||||
self.field_mapper = FlexibleFieldMapper()
|
||||
|
||||
# 保留原有的字段映射作为默认配置(向后兼容)
|
||||
self.field_mapping = {
|
||||
# 核心字段
|
||||
"TR Number": "order_id", # TR编号映射到工单号
|
||||
@@ -75,6 +79,9 @@ class WorkOrderSyncService:
|
||||
"Issue Start Time": "updated_at" # 问题开始时间作为更新时间
|
||||
}
|
||||
|
||||
# 将原有映射添加到灵活映射器中
|
||||
self._init_flexible_mapper()
|
||||
|
||||
# 状态映射 - 根据飞书表格中的实际值
|
||||
self.status_mapping = {
|
||||
"close": WorkOrderStatus.CLOSED, # 已关闭
|
||||
@@ -93,6 +100,62 @@ class WorkOrderSyncService:
|
||||
"Urgent": WorkOrderPriority.URGENT
|
||||
}
|
||||
|
||||
def _init_flexible_mapper(self):
|
||||
"""初始化灵活映射器,将原有映射添加到其中"""
|
||||
for feishu_field, local_field in self.field_mapping.items():
|
||||
self.field_mapper.add_field_mapping(feishu_field, local_field)
|
||||
|
||||
def get_field_discovery_report(self, feishu_fields: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
获取字段发现报告
|
||||
|
||||
Args:
|
||||
feishu_fields: 飞书字段数据
|
||||
|
||||
Returns:
|
||||
字段发现报告
|
||||
"""
|
||||
return self.field_mapper.discover_fields(feishu_fields)
|
||||
|
||||
def add_field_mapping(self, feishu_field: str, local_field: str,
|
||||
aliases: List[str] = None, patterns: List[str] = None,
|
||||
priority: int = 3) -> bool:
|
||||
"""
|
||||
添加字段映射
|
||||
|
||||
Args:
|
||||
feishu_field: 飞书字段名
|
||||
local_field: 本地字段名
|
||||
aliases: 别名列表
|
||||
patterns: 模式列表
|
||||
priority: 优先级
|
||||
|
||||
Returns:
|
||||
是否添加成功
|
||||
"""
|
||||
return self.field_mapper.add_field_mapping(feishu_field, local_field, aliases, patterns, priority)
|
||||
|
||||
def remove_field_mapping(self, feishu_field: str) -> bool:
|
||||
"""
|
||||
移除字段映射
|
||||
|
||||
Args:
|
||||
feishu_field: 飞书字段名
|
||||
|
||||
Returns:
|
||||
是否移除成功
|
||||
"""
|
||||
return self.field_mapper.remove_field_mapping(feishu_field)
|
||||
|
||||
def get_mapping_status(self) -> Dict[str, Any]:
|
||||
"""
|
||||
获取映射状态
|
||||
|
||||
Returns:
|
||||
映射状态信息
|
||||
"""
|
||||
return self.field_mapper.get_mapping_status()
|
||||
|
||||
def sync_from_feishu(self, generate_ai_suggestions: bool = True, limit: int = 10) -> Dict[str, Any]:
|
||||
"""
|
||||
从飞书同步数据到本地系统
|
||||
@@ -387,37 +450,42 @@ class WorkOrderSyncService:
|
||||
|
||||
def _convert_feishu_to_local(self, feishu_fields: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""将飞书字段转换为本地工单字段"""
|
||||
local_data = {}
|
||||
|
||||
logger.info(f"开始转换飞书字段: {feishu_fields}")
|
||||
logger.info(f"字段映射配置: {self.field_mapping}")
|
||||
|
||||
for feishu_field, local_field in self.field_mapping.items():
|
||||
if feishu_field in feishu_fields:
|
||||
value = feishu_fields[feishu_field]
|
||||
logger.info(f"映射字段 {feishu_field} -> {local_field}: {value}")
|
||||
|
||||
# 特殊字段处理
|
||||
if local_field == "status" and value in self.status_mapping:
|
||||
value = self.status_mapping[value]
|
||||
elif local_field == "priority" and value in self.priority_mapping:
|
||||
value = self.priority_mapping[value]
|
||||
elif local_field in ["created_at", "updated_at", "date_of_close"] and value:
|
||||
try:
|
||||
# 处理飞书时间戳(毫秒)
|
||||
if isinstance(value, (int, float)):
|
||||
# 飞书时间戳是毫秒,需要转换为秒
|
||||
value = datetime.fromtimestamp(value / 1000)
|
||||
else:
|
||||
# 处理ISO格式时间字符串
|
||||
value = datetime.fromisoformat(value.replace('Z', '+00:00'))
|
||||
except Exception as e:
|
||||
logger.warning(f"时间字段转换失败: {e}, 使用当前时间")
|
||||
value = datetime.now()
|
||||
|
||||
local_data[local_field] = value
|
||||
else:
|
||||
logger.info(f"飞书字段 {feishu_field} 不存在于数据中")
|
||||
# 使用灵活映射器进行字段转换
|
||||
local_data, conversion_stats = self.field_mapper.convert_fields(feishu_fields)
|
||||
|
||||
# 记录转换统计信息
|
||||
logger.info(f"字段转换统计: 总字段 {conversion_stats['total_fields']}, "
|
||||
f"已映射 {conversion_stats['mapped_fields']}, "
|
||||
f"未映射 {len(conversion_stats['unmapped_fields'])}")
|
||||
|
||||
# 如果有未映射的字段,记录详细信息
|
||||
if conversion_stats['unmapped_fields']:
|
||||
logger.warning(f"未映射字段: {conversion_stats['unmapped_fields']}")
|
||||
for field in conversion_stats['unmapped_fields']:
|
||||
suggestions = conversion_stats['mapping_details'][field].get('suggestions', [])
|
||||
if suggestions:
|
||||
logger.info(f"字段 '{field}' 的建议映射: {suggestions[0] if suggestions else '无'}")
|
||||
|
||||
# 特殊字段处理
|
||||
for local_field, value in local_data.items():
|
||||
if local_field == "status" and value in self.status_mapping:
|
||||
local_data[local_field] = self.status_mapping[value]
|
||||
elif local_field == "priority" and value in self.priority_mapping:
|
||||
local_data[local_field] = self.priority_mapping[value]
|
||||
elif local_field in ["created_at", "updated_at", "date_of_close"] and value:
|
||||
try:
|
||||
# 处理飞书时间戳(毫秒)
|
||||
if isinstance(value, (int, float)):
|
||||
# 飞书时间戳是毫秒,需要转换为秒
|
||||
local_data[local_field] = datetime.fromtimestamp(value / 1000)
|
||||
else:
|
||||
# 处理ISO格式时间字符串
|
||||
local_data[local_field] = datetime.fromisoformat(value.replace('Z', '+00:00'))
|
||||
except Exception as e:
|
||||
logger.warning(f"时间字段转换失败: {e}, 使用当前时间")
|
||||
local_data[local_field] = datetime.now()
|
||||
|
||||
# 生成标题 - 使用TR Number和问题类型
|
||||
tr_number = feishu_fields.get("TR Number", "")
|
||||
|
||||
Reference in New Issue
Block a user