Files
jdy_fastapi/app/tasks/delete_tasks.py
T
2025-12-04 09:46:44 +08:00

345 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
删除相关后台任务模块
本模块包含删除相关的后台任务,包括:
- 删除历史维修记录
- 删除客户信息
- 删除客户车辆信息
这些任务在后台线程中执行,不会阻塞主请求。
执行完成后会更新简道云表单并自动提交工作流。
"""
import logging
import traceback
import requests
import time
from typing import Dict, Any, List, Optional
from datetime import datetime
from tqdm import tqdm
from app.tasks.common import update_jiandaoyun, approve_workflow, get_operate_org_id, get_card_list
logger = logging.getLogger('app')
def delete_history_background(data: Dict[str, Any], cookies: Dict[str, str], org_id: str, org_name: str):
"""
删除历史维修记录后台任务
在后台线程中删除指定门店的历史维修记录。
执行完成后会更新简道云表单并自动提交工作流。
Args:
data: 包含表单ID(api_key)、表单ID(entry_id)、数据ID(data_id)的字典
cookies: 用户登录 F6 系统的 cookies 信息
org_id: 需要删除历史维修记录的门店ID
org_name: 需要删除历史维修记录的门店名称
Returns:
None
"""
url = f'https://yunxiu.f6car.cn/maintain-dump/maintainHistory/?orgid={org_id}' # 删除url
res = requests.delete(url=url, cookies=cookies)
res_data = res.json()
if res.status_code == 200 and res_data.get('code') == 200:
results = f'{org_name} 历史维修记录已删除'
print(results)
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回写改掉 执行明细与执行状态
time.sleep(1)
msg = update_jiandaoyun(data, f'{results}')
if msg.get('msg'):
approve_workflow(data)
print('表单已自动提交至下一步')
def delete_customer_background(data: Dict[str, Any], cookies: Dict[str, str], total:int ):
"""
删除客户信息后台任务
在后台线程中批量删除客户信息。
执行完成后会更新简道云表单并自动提交工作流。
Args:
data: 包含表单ID(api_key)、表单ID(entry_id)、数据ID(data_id)的字典
cookies: 用户登录 F6 系统的 cookies 信息
json_data: 获取到的客户信息列表,包含要删除的客户信息
Returns:
None
注意:
- 8-20点之间每3.5秒删除一条数据,其余时间每1.5秒删除一条数据
- 执行结果会更新到简道云表单
"""
print('开始删除客户信息')
success = 0
fail = 0
json_data = []
total_page = total // 100 + (total % 100 > 0)
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
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],
all_page: str):
"""
删除客户车辆信息后台任务
在后台线程中批量删除客户车辆信息。
会检查车辆是否有会员卡或最近消费记录,有则跳过删除。
执行完成后会更新简道云表单并自动提交工作流。
Args:
data: 包含表单ID(api_key)、表单ID(entry_id)、数据ID(data_id)的字典
url: 获取车辆列表的 API URL
cookies: 用户登录 F6 系统的 cookies 信息
header: HTTP 请求头字典,应包含账号登录的请求头
all_page: 总页数(字符串或整数),用于分页获取车辆列表
Returns:
None
注意:
- 8-20点之间每3.5秒删除一条数据,其余时间每1.5秒删除一条数据
- 有会员卡或最近消费记录的车辆会被跳过
- 执行结果会更新到简道云表单
"""
print(cookies)
success = 0
fail = 0
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 = []
try:
# 获取第一页,确定总页数
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)
total_card = int(card_res.json().get("data", {}).get("total", 0))
if total_card > 0:
total_page = total_card // 100 + (total_card % 100 > 0)
for page in tqdm(range(1, total_page + 1), desc="查询会员卡"):
card_url = (f"https://yunxiu.f6car.cn/marketing/card/paging?useStationIdOwnOrgList={operate_org_id}"
f"&pageSize=100&pageNo={page}")
card_res = requests.get(url=card_url, cookies=cookies)
card_cars_list = card_res.json().get("data", {}).get("data", [])
for card_car in card_cars_list:
if card_car.get("cars") is None:
continue
for car in card_car.get("cars", []):
car_id = car.get("idCar")
if car_id:
card_list_cars.append(car_id)
time.sleep(0.2)
except Exception as e:
logger.error(f"获取会员卡列表时发生错误: {e}")
itemlist = []
# 使用 range() 创建一个可迭代的对象
for page in range(1, all_page + 1):
json_data = {
"pageSize": 100,
"pageNo": page
}
# 获取当前页的数据
res = requests.post(url=url, cookies=cookies, json=json_data, headers=header)
res.raise_for_status() # 检查请求是否成功
response_data = res.json()
if 'data' not in response_data or 'data' not in response_data['data']:
print(f"警告: 页码 {page} 返回的数据格式不正确")
continue
items = response_data['data']['data']
for item in items:
itemlist.append(item)
for item in tqdm(itemlist, desc="删除车辆信息"):
car_id = item.get('tmCarInfo', {}).get('pkId')
customer_id = item.get('tmCustomerInfo', {}).get('pkId')
consume_last_time = item.get('tmCustomerInfo', {}).get('consumeLastTime')
if consume_last_time:
logger.info(f"{customer_id}最近消费时间: {consume_last_time},跳过删除")
fail += 1
continue
if car_id in card_list_cars:
logger.info(f"{customer_id} 存在会员卡,跳过删除")
fail += 1
continue
if not car_id or not customer_id:
logger.info(f"页码 {page} 中缺少必要的ID信息")
fail += 1
continue
try:
delete_url = (
f"https://yunxiu.f6car.cn/member/car/deleteCar/{car_id}/{customer_id}"
)
delete_res = requests.delete(delete_url, cookies=cookies)
delete_res.raise_for_status() # 检查删除请求是否成功
delete_data = delete_res.json()
if delete_data.get('data'):
success += 1
else:
fail += 1
logger.error(
f"删除失败: 页码 {page}, 车辆ID {car_id}, 客户ID {customer_id},"
f" 错误信息: {delete_data.get('message', '未知错误')}")
print(
f"删除失败: 页码 {page}, 车辆ID {car_id}, 客户ID {customer_id},"
f" 错误信息: {delete_data.get('message', '未知错误')}")
time.sleep(0.2) # 避免过快请求
except requests.exceptions.RequestException as e:
fail += 1
print(f"删除失败: 页码 {page}, 车辆ID {car_id}, 客户ID {customer_id}, 错误信息: {e}")
logger.error(f"删除失败: 页码 {page}, 车辆ID {car_id}, 客户ID {customer_id}, 错误信息: {e}")
continue
now = datetime.now()
if 20 <= now.hour <= 8:
time.sleep(1)
else:
time.sleep(3)
print(f"完成: 成功删除 {success} 辆车, 失败 {fail} 辆车")
logger.info(f"完成: 成功删除 {success} 辆车, 失败 {fail} 辆车")
except ValueError as e:
print(f"Error converting all_page to integer: {e}")
traceback.print_exc() # 打印堆栈跟踪信息
except Exception as e:
print(f"An unexpected error occurred: {e}")
traceback.print_exc() # 打印堆栈跟踪信息
msg = update_jiandaoyun(data, f'成功次数{success},失败次数{fail}')
if msg.get('msg'):
approve_workflow(data)
print('表单已自动提交至下一步')