新增失败预警功能

This commit is contained in:
z66
2025-12-11 09:52:59 +08:00
parent 1e83d5b19a
commit 70c375a34e
3 changed files with 199 additions and 158 deletions
+7 -7
View File
@@ -65,7 +65,7 @@ class F6PluginModule:
Returns: Returns:
tuple: 包含文件保存路径和处理后的数据的元组。如果文件保存成功,返回保存路径和数据;如果失败,返回 None 和数据。 tuple: 包含文件保存路径和处理后的数据的元组。如果文件保存成功,返回保存路径和数据;如果失败,返回 None 和数据。
""" """
data = api_instance.entry_data_get(data=data) data = api_instance.entry_data_get(data=data,replace= True)
print(data) print(data)
try: try:
# 安全地访问附件信息 # 安全地访问附件信息
@@ -191,7 +191,7 @@ class F6PluginModule:
Returns: Returns:
Dict[str, str]: 包含执行状态的字典,{'msg': '正在执行', 'msg_details': '正在执行,请稍后看结果'} Dict[str, str]: 包含执行状态的字典,{'msg': '正在执行', 'msg_details': '正在执行,请稍后看结果'}
""" """
entry_data = api_instance.entry_data_get(data=data) entry_data = api_instance.entry_data_get(data=data,replace= True)
print('执行 品牌批量新建') print('执行 品牌批量新建')
username = entry_data['data']['账号'] username = entry_data['data']['账号']
password = entry_data['data']['密码'] password = entry_data['data']['密码']
@@ -232,7 +232,7 @@ class F6PluginModule:
Returns: Returns:
Dict[str, str]: 包含执行状态的字典 Dict[str, str]: 包含执行状态的字典
""" """
entry_data = api_instance.entry_data_get(data=data) entry_data = api_instance.entry_data_get(data=data,replace= True)
username = entry_data['data']['账号'] username = entry_data['data']['账号']
password = entry_data['data']['密码'] password = entry_data['data']['密码']
company_name = entry_data['data']['公司名称'] company_name = entry_data['data']['公司名称']
@@ -279,7 +279,7 @@ class F6PluginModule:
Dict[str, str]: 包含执行状态的字典 Dict[str, str]: 包含执行状态的字典
""" """
print('执行 删除客户') print('执行 删除客户')
entry_data = api_instance.entry_data_get(data=data) entry_data = api_instance.entry_data_get(data=data,replace= True)
username = entry_data['data']['账号'] username = entry_data['data']['账号']
password = entry_data['data']['密码'] password = entry_data['data']['密码']
company_name = entry_data['data']['公司名称'] company_name = entry_data['data']['公司名称']
@@ -318,7 +318,7 @@ class F6PluginModule:
Returns: Returns:
Dict[str, str]: 包含执行状态的字典 Dict[str, str]: 包含执行状态的字典
""" """
entry_data = api_instance.entry_data_get(data=data) entry_data = api_instance.entry_data_get(data=data,replace= True)
username = entry_data['data']['账号'] username = entry_data['data']['账号']
password = entry_data['data']['密码'] password = entry_data['data']['密码']
company_name = entry_data['data']['公司名称'] company_name = entry_data['data']['公司名称']
@@ -364,7 +364,7 @@ class F6PluginModule:
Returns: Returns:
Dict[str, str]: 包含执行状态的字典 Dict[str, str]: 包含执行状态的字典
""" """
entry_data = api_instance.entry_data_get(data=data) entry_data = api_instance.entry_data_get(data=data,replace= True)
username = entry_data['data']['账号'] username = entry_data['data']['账号']
password = entry_data['data']['密码'] password = entry_data['data']['密码']
company_name = entry_data['data']['公司名称'] company_name = entry_data['data']['公司名称']
@@ -403,7 +403,7 @@ class F6PluginModule:
Returns: Returns:
Dict[str, str]: 包含执行状态的字典,{'msg': '正在执行', 'msg_details': '正在执行,请稍后看结果'} Dict[str, str]: 包含执行状态的字典,{'msg': '正在执行', 'msg_details': '正在执行,请稍后看结果'}
""" """
entry_data = api_instance.entry_data_get(data=data) entry_data = api_instance.entry_data_get(data=data,replace= True)
print('执行 BI任务') print('执行 BI任务')
# 获取必要的参数(根据实际需求调整) # 获取必要的参数(根据实际需求调整)
+22
View File
@@ -117,6 +117,28 @@ def approve_workflow(data: Dict[str, Any]):
logger.error(f"简道云工作流任务提交失败: {e}") logger.error(f"简道云工作流任务提交失败: {e}")
def execute_failure_handler(data: Dict[str, Any]):
"""
简道云失败流程通知
函数执行失败时调用,通过钉钉webhook通知到指定人员
"""
now = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
pay_load = {
"api_key":"6694d3c4fcb69ca9a111a6c4",
"entry_id":"6938e011b360a1132522a62a",
"data": {
"_widget_1765335060501": {"value": now}, # 失败时间
"_widget_1765335060502": {"value": data['failure_name']}, # 任务名称
"_widget_1765335060503": {"value": data['failure_details']} # 失败明细
}
}
api_instance.data_batch_create(pay_load)
def get_operate_org_id(cookies: Dict[str, str]) -> Optional[str]: def get_operate_org_id(cookies: Dict[str, str]) -> Optional[str]:
""" """
获取操作门店ID 获取操作门店ID
+168 -149
View File
@@ -16,7 +16,8 @@ import time
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from datetime import datetime from datetime import datetime
from tqdm import tqdm from tqdm import tqdm
from app.tasks.common import update_jiandaoyun, approve_workflow, get_operate_org_id, get_card_list from app.tasks.common import update_jiandaoyun, approve_workflow, get_operate_org_id, get_card_list, \
execute_failure_handler
logger = logging.getLogger('app') logger = logging.getLogger('app')
@@ -37,29 +38,39 @@ def delete_history_background(data: Dict[str, Any], cookies: Dict[str, str], org
Returns: Returns:
None None
""" """
url = f'https://yunxiu.f6car.cn/maintain-dump/maintainHistory/?orgid={org_id}' # 删除url try:
res = requests.delete(url=url, cookies=cookies)
res_data = res.json()
if res.status_code == 200 and res_data.get('code') == 200: url = f'https://yunxiu.f6car.cn/maintain-dump/maintainHistory/?orgid={org_id}' # 删除url
results = f'{org_name} 历史维修记录已删除' res = requests.delete(url=url, cookies=cookies)
print(results) res_data = res.json()
logger.info(f"删除 {org_name} 历史维修记录成功")
else:
results = f'删除 {org_name} 历史维修记录失败: {res_data.get("message")}'
print(results)
logger.error(f"删除 {org_name} 历史维修记录失败: {res_data.get('message')}")
# 调用api回写改掉 执行明细与执行状态 if res.status_code == 200 and res_data.get('code') == 200:
time.sleep(1) results = f'{org_name} 历史维修记录已删除'
msg = update_jiandaoyun(data, f'{results}') print(results)
logger.info(f"删除 {org_name} 历史维修记录成功")
else:
results = f'删除 {org_name} 历史维修记录失败: {res_data.get("message")}'
data["failure_name"] = "删除历史维修记录后台任务"
data["failure_details"] = results
execute_failure_handler(data)
logger.error(f"删除 {org_name} 历史维修记录失败: {res_data.get('message')}")
if msg.get('msg'): # 调用api回写改掉 执行明细与执行状态
approve_workflow(data) time.sleep(1)
print('表单已自动提交至下一步') msg = update_jiandaoyun(data, f'{results}')
if msg.get('msg'):
approve_workflow(data)
print('表单已自动提交至下一步')
except Exception as e:
logger.error(f"删除 {org_name} 历史维修记录失败: {e}")
logger.error(traceback.format_exc())
data["failure_name"] = "删除历史维修记录后台任务"
data["failure_details"] = traceback.format_exc()
execute_failure_handler(data)
def delete_customer_background(data: Dict[str, Any], cookies: Dict[str, str], total:int ): def delete_customer_background(data: Dict[str, Any], cookies: Dict[str, str], total: int):
""" """
删除客户信息后台任务 删除客户信息后台任务
@@ -78,110 +89,118 @@ def delete_customer_background(data: Dict[str, Any], cookies: Dict[str, str], to
- 8-20点之间每3.5秒删除一条数据,其余时间每1.5秒删除一条数据 - 8-20点之间每3.5秒删除一条数据,其余时间每1.5秒删除一条数据
- 执行结果会更新到简道云表单 - 执行结果会更新到简道云表单
""" """
print('开始删除客户信息') try:
success = 0 logger.info("开始删除客户信息")
fail = 0 success = 0
fail = 0
json_data = []
total_page = total // 100 + (total % 100 > 0)
logger.info("正在加载客户信息")
for page in tqdm(range(1, total_page + 1)):
url = f"https://yunxiu.f6car.cn/member/customer/listForPermission?pageSize=100&pageNo={page}"
res = requests.get(url, cookies=cookies)
json_data.extend(res.json().get('data', {}).get('data', []))
# 获取门店ID
operate_org_id = get_operate_org_id(cookies)
if not operate_org_id:
msg = update_jiandaoyun(data, '删除失败: 未获取到门店信息')
if msg.get('msg'):
approve_workflow(data)
return
json_data = [] # 获取会员卡列表(提取客户ID
total_page = total // 100 + (total % 100 > 0) card_list_customers = get_card_list(cookies, operate_org_id)
for page in tqdm(range(1, total_page + 1)):
url = f"https://yunxiu.f6car.cn/member/customer/listForPermission?pageSize=100&pageNo={page}" for item in tqdm(json_data, desc="删除客户"):
res = requests.get(url, cookies=cookies) id_customer = item['idCustomer']
json_data.extend(res.json().get('data', {}).get('data',[])) phone = item['cellPhone']
consume_last_time = item['consumeLastTime']
if consume_last_time:
print(f'{id_customer}最近消费时间: {consume_last_time},跳过删除')
logger.warning(f"{id_customer}最近消费时间: {consume_last_time},跳过删除")
continue
if id_customer in card_list_customers:
logger.info(f"{id_customer} 存在会员卡,跳过删除")
fail += 1
continue
try:
url = f"https://yunxiu.f6car.cn/member/customer/{id_customer}" # 客户信息删除url
res = requests.delete(url, cookies=cookies, timeout=10) # 客户信息删除
# 检查HTTP状态码
if res.status_code != 200:
fail += 1
error_msg = f"HTTP状态码错误: {res.status_code}"
logger.error(f"客户删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
time.sleep(0.2)
continue
# 解析响应数据
try:
res_data = res.json()
except ValueError as json_error:
fail += 1
error_msg = f"响应不是有效的JSON格式: {json_error}, 响应内容: {res.text[:200]}"
logger.error(f"客户删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
time.sleep(0.2)
continue
# 检查多种可能的成功标识
# 有些API返回 success 字段,有些返回 code=200,有些返回 data 字段
is_success = (
res_data.get('success') is True or
res_data.get('code') == 200 or
(res_data.get('code') is None and res_data.get('data') is not None)
)
if is_success:
success += 1
logger.info(f"客户删除成功: ID={id_customer}, 手机号={phone}")
else:
fail += 1
error_msg = res_data.get('message') or res_data.get('msg') or '未知错误'
error_detail = f"错误信息: {error_msg}, 完整响应: {res_data}"
logger.error(f"客户删除失败: ID={id_customer}, 手机号={phone}, {error_detail}")
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
time.sleep(0.2)
except requests.exceptions.RequestException as e:
fail += 1
error_msg = f"网络请求异常: {str(e)}"
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
logger.error(f"删除客户时发生网络错误: ID={id_customer}, 手机号={phone}, {error_msg}")
except Exception as e:
fail += 1
error_msg = f"未知错误: {str(e)}"
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
logger.error(f"删除客户时发生错误: ID={id_customer}, 手机号={phone}, {error_msg}", exc_info=True)
now = datetime.now()
if 8 <= now.hour <= 20:
time.sleep(3.5)
else:
time.sleep(1.5)
logger.info(f"客户删除结果: 成功次数={success}, 失败次数={fail}")
msg = update_jiandaoyun(data, f'成功次数{success},失败次数{fail}')
# 获取门店ID
operate_org_id = get_operate_org_id(cookies)
if not operate_org_id:
msg = update_jiandaoyun(data, '删除失败: 未获取到门店信息')
if msg.get('msg'): if msg.get('msg'):
approve_workflow(data) approve_workflow(data)
return print('表单已自动提交至下一步')
except Exception as e:
logger.error(f"删除客户信息时发生错误: {str(e)}")
logger.error(traceback.format_exc())
data["failure_name"] = "删除客户信息后台任务"
data["failure_details"] = traceback.format_exc()
execute_failure_handler(data)
print(operate_org_id)
# 获取会员卡列表(提取客户ID
card_list_customers = get_card_list(cookies, operate_org_id)
for item in tqdm(json_data, desc="删除客户"):
id_customer = item['idCustomer']
phone = item['cellPhone']
consume_last_time = item['consumeLastTime']
if consume_last_time:
print(f'{id_customer}最近消费时间: {consume_last_time},跳过删除')
logger.warning(f"{id_customer}最近消费时间: {consume_last_time},跳过删除")
continue
if id_customer in card_list_customers:
logger.info(f"{id_customer} 存在会员卡,跳过删除")
fail += 1
continue
try:
url = f"https://yunxiu.f6car.cn/member/customer/{id_customer}" # 客户信息删除url
res = requests.delete(url, cookies=cookies, timeout=10) # 客户信息删除
# 检查HTTP状态码
if res.status_code != 200:
fail += 1
error_msg = f"HTTP状态码错误: {res.status_code}"
logger.error(f"客户删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
time.sleep(0.2)
continue
# 解析响应数据
try:
res_data = res.json()
except ValueError as json_error:
fail += 1
error_msg = f"响应不是有效的JSON格式: {json_error}, 响应内容: {res.text[:200]}"
logger.error(f"客户删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
time.sleep(0.2)
continue
# 检查多种可能的成功标识
# 有些API返回 success 字段,有些返回 code=200,有些返回 data 字段
is_success = (
res_data.get('success') is True or
res_data.get('code') == 200 or
(res_data.get('code') is None and res_data.get('data') is not None)
)
if is_success:
success += 1
logger.info(f"客户删除成功: ID={id_customer}, 手机号={phone}")
else:
fail += 1
error_msg = res_data.get('message') or res_data.get('msg') or '未知错误'
error_detail = f"错误信息: {error_msg}, 完整响应: {res_data}"
logger.error(f"客户删除失败: ID={id_customer}, 手机号={phone}, {error_detail}")
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
time.sleep(0.2)
except requests.exceptions.RequestException as e:
fail += 1
error_msg = f"网络请求异常: {str(e)}"
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
logger.error(f"删除客户时发生网络错误: ID={id_customer}, 手机号={phone}, {error_msg}")
except Exception as e:
fail += 1
error_msg = f"未知错误: {str(e)}"
print(f"删除失败: ID={id_customer}, 手机号={phone}, {error_msg}")
logger.error(f"删除客户时发生错误: ID={id_customer}, 手机号={phone}, {error_msg}", exc_info=True)
now = datetime.now()
if 8 <= now.hour <= 20:
time.sleep(3.5)
else:
time.sleep(1.5)
logger.info(f"客户删除结果: 成功次数={success}, 失败次数={fail}")
msg = update_jiandaoyun(data, f'成功次数{success},失败次数{fail}')
if msg.get('msg'):
approve_workflow(data)
print('表单已自动提交至下一步')
def delete_car_background(data: Dict[str, Any], url: str, cookies: Dict[str, str], header: Dict[str, Any], def delete_car_background(data: Dict[str, Any], url: str, cookies: Dict[str, str], header: Dict[str, Any],
@@ -208,27 +227,28 @@ def delete_car_background(data: Dict[str, Any], url: str, cookies: Dict[str, str
- 有会员卡或最近消费记录的车辆会被跳过 - 有会员卡或最近消费记录的车辆会被跳过
- 执行结果会更新到简道云表单 - 执行结果会更新到简道云表单
""" """
print(cookies)
success = 0
fail = 0
try: try:
# 确保 all_page 是一个整数 print(cookies)
all_page = int(all_page) success = 0
fail = 0
# 获取门店ID
operate_org_id = get_operate_org_id(cookies)
if not operate_org_id:
msg = update_jiandaoyun(data, '删除失败: 未获取到门店信息')
if msg.get('msg'):
approve_workflow(data)
return
print(operate_org_id)
# 获取会员卡列表(提取车辆ID
# 注意:需要获取所有车辆的ID,所以不能直接使用 get_card_list
# 需要自定义提取逻辑,返回所有车辆的ID列表
card_list_cars = []
try: try:
# 确保 all_page 是一个整数
all_page = int(all_page)
# 获取门店ID
operate_org_id = get_operate_org_id(cookies)
if not operate_org_id:
msg = update_jiandaoyun(data, '删除失败: 未获取到门店信息')
if msg.get('msg'):
approve_workflow(data)
return
print(operate_org_id)
# 获取会员卡列表(提取车辆ID
# 注意:需要获取所有车辆的ID,所以不能直接使用 get_card_list
# 需要自定义提取逻辑,返回所有车辆的ID列表
card_list_cars = []
# 获取第一页,确定总页数 # 获取第一页,确定总页数
card_url = f"https://yunxiu.f6car.cn/marketing/card/paging?useStationIdOwnOrgList={operate_org_id}&pageSize=100&pageNo=1" card_url = f"https://yunxiu.f6car.cn/marketing/card/paging?useStationIdOwnOrgList={operate_org_id}&pageSize=100&pageNo=1"
card_res = requests.get(url=card_url, cookies=cookies) card_res = requests.get(url=card_url, cookies=cookies)
@@ -238,7 +258,7 @@ def delete_car_background(data: Dict[str, Any], url: str, cookies: Dict[str, str
total_page = total_card // 100 + (total_card % 100 > 0) total_page = total_card // 100 + (total_card % 100 > 0)
for page in tqdm(range(1, total_page + 1), desc="查询会员卡"): for page in tqdm(range(1, total_page + 1), desc="查询会员卡"):
card_url = (f"https://yunxiu.f6car.cn/marketing/card/paging?useStationIdOwnOrgList={operate_org_id}" card_url = (f"https://yunxiu.f6car.cn/marketing/card/paging?useStationIdOwnOrgList={operate_org_id}"
f"&pageSize=100&pageNo={page}") f"&pageSize=100&pageNo={page}")
card_res = requests.get(url=card_url, cookies=cookies) card_res = requests.get(url=card_url, cookies=cookies)
card_cars_list = card_res.json().get("data", {}).get("data", []) card_cars_list = card_res.json().get("data", {}).get("data", [])
@@ -329,16 +349,15 @@ def delete_car_background(data: Dict[str, Any], url: str, cookies: Dict[str, str
print(f"完成: 成功删除 {success} 辆车, 失败 {fail} 辆车") print(f"完成: 成功删除 {success} 辆车, 失败 {fail} 辆车")
logger.info(f"完成: 成功删除 {success} 辆车, 失败 {fail} 辆车") logger.info(f"完成: 成功删除 {success} 辆车, 失败 {fail} 辆车")
except ValueError as e:
print(f"Error converting all_page to integer: {e}") msg = update_jiandaoyun(data, f'成功次数{success},失败次数{fail}')
traceback.print_exc() # 打印堆栈跟踪信息
if msg.get('msg'):
approve_workflow(data)
print('表单已自动提交至下一步')
except Exception as e: except Exception as e:
print(f"An unexpected error occurred: {e}") logger.error(f"删除客户车辆信息时发生错误: {str(e)}")
traceback.print_exc() # 打印堆栈跟踪信息 logger.error(traceback.format_exc())
data["failure_name"] = "删除客户车辆信息后台任务"
msg = update_jiandaoyun(data, f'成功次数{success},失败次数{fail}') data["failure_details"] = traceback.format_exc()
execute_failure_handler(data)
if msg.get('msg'):
approve_workflow(data)
print('表单已自动提交至下一步')