361 lines
19 KiB
Python
361 lines
19 KiB
Python
from datetime import date, timedelta, datetime
|
|
import holidays
|
|
from config import Config
|
|
import pandas as pd
|
|
import pymysql # 使用 pymysql 替代 mysql.connector
|
|
from log_config import configure_task_logger, configure_error_task_logger
|
|
from api import API
|
|
from back_ground_module import CommonModule
|
|
common_module = CommonModule()
|
|
api_instance = API()
|
|
global last_day_end_customer_service, is_customer_service_data_id, customer_service_data_id
|
|
|
|
|
|
class JCBAbnormalRevisit:
|
|
"""接车宝异常回访"""
|
|
def __init__(self):
|
|
# 使用 pymysql 连接数据库
|
|
self.daily_revisit_list = None
|
|
self.abnormal_list = None
|
|
self.field_mapping = {}
|
|
self.staff_id_list = None
|
|
self.customer_service_list = None
|
|
|
|
def load_all_data(self):
|
|
# 获取接车宝异常待办
|
|
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
|
"entry_id": "67c156ba635191b64af8a110",
|
|
}
|
|
abnormal_service = api_instance.entry_data_list(payload)
|
|
self.abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
|
|
|
|
# 获取接车宝日常回访单
|
|
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
|
"entry_id": "67174710da507490d8ac12c1",
|
|
}
|
|
daily_revisit = api_instance.entry_data_list(payload)
|
|
self.daily_revisit_list = daily_revisit.get("data") # api请求格式,将数据封装在data字典里
|
|
|
|
def load_cus_data(self):
|
|
# 获取接车宝客服表单
|
|
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
|
"entry_id": "67b6f2462f9ac03b783d409a",
|
|
}
|
|
customer_service = api_instance.entry_data_list(payload)
|
|
customer_service_list = customer_service.get("data") # api请求格式,将数据封装在data字典里
|
|
return customer_service_list
|
|
|
|
def today_customer_service_list(self):
|
|
# 获取今日接车宝派发客服顺序
|
|
today_customer_service_list = []
|
|
all_customer_service_list = []
|
|
today_customer_service_start_list = []
|
|
for row_items in self.load_cus_data():
|
|
# print(row_items)
|
|
customer_service_name_id = row_items.get("_widget_1740042824214", {}).get("username", {})
|
|
customer_service_name = row_items.get("_widget_1740042824214", {}).get("name", {})
|
|
customer_service_state = row_items.get("_widget_1740117343937", {})
|
|
is_last_day_end = row_items.get("_widget_1740042824216", {})
|
|
customer_service_data_id = row_items.get("_id", {})
|
|
print(customer_service_name, customer_service_name_id, customer_service_state, is_last_day_end)
|
|
all_customer_service_list.append(
|
|
[customer_service_name, customer_service_name_id, customer_service_state, is_last_day_end,
|
|
customer_service_data_id])
|
|
if is_last_day_end == "是": # 判断是否是下次开始位置
|
|
last_day_end_customer_service = customer_service_name_id
|
|
is_customer_service_data_id = row_items.get("_id", {})
|
|
|
|
split_index = None
|
|
for index, row in enumerate(all_customer_service_list):
|
|
print(row[3])
|
|
if row[3] == "是":
|
|
split_index = index
|
|
print(f"找到索引 {index}")
|
|
break
|
|
|
|
if split_index is not None:
|
|
# 根据索引切割列表
|
|
first_part = all_customer_service_list[split_index:] # 索引位置及之后的行
|
|
second_part = all_customer_service_list[:split_index] # 索引位置之前的行
|
|
# 调换两个子列表的位置并重新组合
|
|
today_customer_service_start_list = first_part + second_part
|
|
else:
|
|
# 如果没有找到“是”,保持原列表不变
|
|
today_customer_service_start_list = all_customer_service_list
|
|
pass
|
|
|
|
for index, row in enumerate(today_customer_service_start_list):
|
|
if row[2] == "开":
|
|
today_customer_service_list.append(row[1])
|
|
|
|
return today_customer_service_list, is_customer_service_data_id, all_customer_service_list
|
|
|
|
def send_request(self, df):
|
|
today_customer_service_list, is_customer_service_data_id, all_customer_service_list = self.today_customer_service_list()
|
|
# 初始化派发索引
|
|
next_dispatcher_index = 0
|
|
|
|
# 显式循环分配跟进人
|
|
follow_up_persons = []
|
|
for _ in range(len(df)):
|
|
follow_up_person = today_customer_service_list[next_dispatcher_index]
|
|
follow_up_persons.append(follow_up_person)
|
|
next_dispatcher_index = (next_dispatcher_index + 1) % len(today_customer_service_list)
|
|
|
|
# 添加跟进人到 DataFrame
|
|
df["跟进人"] = follow_up_persons
|
|
|
|
# 获取下一个派发人
|
|
next_dispatcher = today_customer_service_list[next_dispatcher_index]
|
|
|
|
new_sign_abnormal_data = [self.row_to_dict(row, self.field_mapping) for index, row in
|
|
df.iterrows()]
|
|
|
|
data = {'api_key': Config.EFFICIENT_CAR_PICKUP_APP_ID, 'entry_id': "67174710da507490d8ac12c1",
|
|
"data_list": new_sign_abnormal_data} # 派发数据
|
|
|
|
api_instance.entry_data_batch_create(data)
|
|
|
|
data1 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
|
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
|
|
"data_id": is_customer_service_data_id,
|
|
"data":
|
|
{"_widget_1740042824216": {"value": ""}, }
|
|
} # 原来的是"_widget_1740042824216": {"value": "是"},修改昨日截至人员
|
|
next_customer_service_data_id = None
|
|
for index, row in enumerate(all_customer_service_list):
|
|
print(row[3])
|
|
if row[1] == next_dispatcher:
|
|
next_customer_service_data_id = row[4]
|
|
break
|
|
|
|
data2 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
|
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
|
|
"data_id": next_customer_service_data_id,
|
|
"data":
|
|
{"_widget_1740042824216": {"value": "是"}, }}# 明日派发起点人员
|
|
|
|
api_instance.entry_data_update(data1)
|
|
api_instance.entry_data_update(data2)
|
|
|
|
def main(self):
|
|
self.load_all_data()
|
|
task_start_time =datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
data_JCB = common_module.get_jcb_details()
|
|
|
|
# 保存为CSV文件
|
|
output_dir = "output" # 设置输出目录
|
|
|
|
# 创建输出目录(如果不存在)
|
|
import os
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
|
|
# data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
|
|
self.fields()
|
|
|
|
# 异常待办回访 近1个月开单为0客户
|
|
# 当前日期
|
|
current_date = datetime.now()
|
|
current_date = current_date + timedelta(days=1)
|
|
current_date_str = current_date.strftime("%Y-%m-%d")
|
|
# current_date = datetime.now()
|
|
thirty_days_ago = current_date - timedelta(days=30)
|
|
thirty_days_ago = thirty_days_ago.date()
|
|
abnormal_data = []
|
|
JDY_abnormal_data = []
|
|
JDY_revisit_data = []
|
|
# df = pd.read_csv(os.path.join(output_dir, "JCB_异常待办.csv")) # 读取异常待办表
|
|
# print(df)
|
|
for index, row in data_JCB.iterrows():
|
|
new_row = row.copy()
|
|
new_row['开户日'] = datetime.strptime(new_row['开户日'], "%Y-%m-%d").date()
|
|
if new_row['开户日'] < thirty_days_ago and row['近30天开单天数'] == 0 and row['客户状态'] == "留存":
|
|
# print(row['账号'], row['开户日'], row['近30天开单天数'], row["客户状态"])
|
|
row["日期"] = datetime.strptime(row['开户日'], "%Y-%m-%d").date()
|
|
row['日期'] = row["日期"].strftime("%Y-%m-%d")
|
|
abnormal_data.append(row)
|
|
# 推送给客服
|
|
abnormal_data = pd.DataFrame(abnormal_data)
|
|
abnormal_data["表单类型"] = "异常待办"
|
|
abnormal_data["派发日期"] = current_date_str
|
|
# abnormal_data.to_excel(os.path.join(output_dir, 'JCB_异常待办.xlsx'), index=False) # 派发B(所有异常待办)
|
|
|
|
for abnormal_items in self.abnormal_list:
|
|
last_send_date = abnormal_items.get("_widget_1740723898405", {}) # 派发日期
|
|
last_30_days_orders = abnormal_items.get("_widget_1740723898401", {}) # 近30天开单数
|
|
phone = abnormal_items.get("_widget_1740723898391", {}) # 手机号
|
|
account = abnormal_items.get("_widget_1740723898390", {}) # 账号
|
|
data_id = abnormal_items.get("_id", {}) # 数据id
|
|
JDY_abnormal_data.append([data_id, account, phone, last_send_date, last_30_days_orders])
|
|
|
|
JDY_abnormal_data = pd.DataFrame(JDY_abnormal_data,
|
|
columns=["数据id", "账号", "联系手机号", "派发日期",
|
|
"近30天开单天数"]) # 派发A(简道云上异常待办)
|
|
# JDY_abnormal_data.columns = ["数据id", "账号", "联系手机号", "派发日期", "近30天开单天数"]
|
|
# JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_云端异常待办.xlsx'), index=False) # 派发A
|
|
|
|
# 将 '联系手机号' 列转换为字符串类型
|
|
JDY_abnormal_data['联系手机号'] = JDY_abnormal_data['联系手机号'].astype(str).str.replace('.0', '')
|
|
abnormal_data['联系手机号'] = abnormal_data['联系手机号'].astype(str)
|
|
# JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_云端异常待办.xlsx'), index=False) # 派发A
|
|
# abnormal_data.to_excel(os.path.join(output_dir, 'JCB_今日异常待办.xlsx'), index=False) # 派发B
|
|
|
|
today = datetime.now().weekday()
|
|
|
|
# 随机抽40条派发
|
|
df_40 = pd.DataFrame()
|
|
if 0 <= today <= 4:
|
|
# if 1>2:
|
|
# 假设 JDY_abnormal_data 和 abnormal_data 都有重复列 '重复列'
|
|
df3 = pd.merge(JDY_abnormal_data, abnormal_data, on=["联系手机号", "账号"], how='inner',
|
|
suffixes=('', '_y'))
|
|
# 删除以 _y 结尾的列(即来自右侧 DataFrame 的重复列)
|
|
df3 = df3.loc[:, ~df3.columns.str.endswith('_y')]
|
|
df3['派发日期'] = pd.to_datetime(df3['派发日期']).dt.strftime("%Y-%m-%d")
|
|
# df3.to_excel(os.path.join(output_dir, 'JCB_异常待办情况1.xlsx'),
|
|
# index=False, ) # B存在,A存在 ,今日派发与历史派发都存在,派发并删历史
|
|
|
|
df_40 = df3[df3.index < 40]
|
|
# df_40.to_excel(os.path.join(output_dir, 'JCB_异常待办情况2.xlsx'), index=False, )
|
|
|
|
for index, row in df_40.iterrows(): # 删除已推送的数据
|
|
delete_data = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
|
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_HISTORY_ID,
|
|
"data_id": row["数据id"]}
|
|
# print(delete_data)
|
|
api_instance.entry_data_delete(delete_data)
|
|
|
|
# B不存在A存在 今日派发不存在,历史存在,删历史
|
|
# 使用 outer 合并,并添加指示器列 _merge
|
|
df_merged = pd.merge(JDY_abnormal_data, abnormal_data, on=["联系手机号", "账号"], how='outer', indicator=True,
|
|
suffixes=('', '_y')) # outer保留所有数据,indicator标注来源
|
|
# 筛选出只存在于 JDY_abnormal_data 中的行
|
|
df_a_not_in_b = df_merged[df_merged['_merge'] == 'left_only']
|
|
# 删除以 _y 结尾的列(即来自右侧 DataFrame 的重复列)
|
|
df_a_not_in_b = df_a_not_in_b.loc[:, ~df_a_not_in_b.columns.str.endswith('_y')]
|
|
df_a_not_in_b['派发日期'] = pd.to_datetime(df_a_not_in_b['派发日期']).dt.strftime("%Y-%m-%d")
|
|
# 保存到 Excel 文件
|
|
# df_a_not_in_b.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_A存在B不存在.xlsx'), index=False)
|
|
for index, row in df_a_not_in_b.iterrows(): # 删除已推送的数据
|
|
delete_data = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
|
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_HISTORY_ID,
|
|
"data_id": row["数据id"]}
|
|
# print(delete_data)
|
|
api_instance.entry_data_delete(delete_data)
|
|
|
|
# B存在A不存在 今日派发存在,历史不存在,为新增异常,直接派发
|
|
df_merged = pd.merge(JDY_abnormal_data, abnormal_data, on=["联系手机号", "账号"], how='outer', indicator=True,
|
|
suffixes=('_x', '')) # outer保留所有数据,indicator标注来源
|
|
# df_merged.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在_134434.xlsx'), index=False)
|
|
# 筛选出只存在于 JDY_abnormal_data 中的行
|
|
df_b_not_in_a = df_merged[df_merged['_merge'] == 'right_only']
|
|
# df_b_not_in_a.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在_111.xlsx'), index=False)
|
|
# 删除以 _y 结尾的列(即来自右侧 DataFrame 的重复列)
|
|
df_b_not_in_a = df_b_not_in_a.loc[:, ~df_b_not_in_a.columns.str.endswith('_x')]
|
|
# df_b_not_in_a.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在_122.xlsx'), index=False)
|
|
df_b_not_in_a['派发日期'] = pd.to_datetime(df_b_not_in_a['派发日期']).dt.strftime("%Y-%m-%d")
|
|
# 保存到 Excel 文件
|
|
# df_b_not_in_a.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在.xlsx'), index=False)
|
|
|
|
# 合并两个当日派发的df
|
|
df_abnormal_data = pd.concat([df_40, df_b_not_in_a], ignore_index=True)
|
|
# df_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_合并当日派发.xlsx'), index=False)
|
|
|
|
for abnormal_items in self.daily_revisit_list: # 遍历云端已经派发的数据
|
|
account = abnormal_items.get("_widget_1739258942667", {}) # 账号
|
|
sub_date = abnormal_items.get("createTime", {}) # 提交时间
|
|
update_date = abnormal_items.get("updateTime", {}) # 更新时间
|
|
entry_style = abnormal_items.get("_widget_1739951204545", {}) # 表单类型
|
|
entry_type = abnormal_items.get("flowState", {}) # 表单状态 0流转中 1流转完成 2 手动结束
|
|
|
|
data_id = abnormal_items.get("_id", {}) # 数据id
|
|
JDY_revisit_data.append([data_id, account, sub_date, update_date, entry_style, entry_type])
|
|
|
|
JDY_revisit_data = pd.DataFrame(JDY_revisit_data)
|
|
JDY_revisit_data.columns = ["数据id", "账号", "提交时间", "更新时间", "表单类型", "表单状态"]
|
|
# JDY_revisit_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_原始数据.xlsx'), index=False)
|
|
|
|
filtered_data = JDY_revisit_data[JDY_revisit_data['表单类型'] == '异常待办'] # 过滤表单类型
|
|
# filtered_data = filtered_data[filtered_data['表单状态'] == 1] # 过滤表单状态
|
|
# filtered_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_过滤数据.xlsx'), index=False)
|
|
|
|
filtered_data['提交时间'] = pd.to_datetime(filtered_data['提交时间']).dt.strftime("%Y-%m-%d")
|
|
latest_update_time = filtered_data.groupby('账号')['提交时间'].max().reset_index()
|
|
latest_update_time.rename(columns={'提交时间': '最新提交时间'}, inplace=True)
|
|
|
|
|
|
filtered_data_with_latest = pd.merge(
|
|
filtered_data,
|
|
latest_update_time,
|
|
left_on=['账号', '提交时间'],
|
|
right_on=['账号', '最新提交时间']
|
|
)
|
|
|
|
# 过滤出每个账号中提交时间为最新的记录
|
|
latest_JDY_abnormal_data = filtered_data_with_latest[
|
|
filtered_data_with_latest['提交时间'] == filtered_data_with_latest['最新提交时间']
|
|
]
|
|
# latest_JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_最新数据_1.xlsx'), index=False)
|
|
|
|
|
|
latest_JDY_abnormal_data['提交时间'] = pd.to_datetime(latest_JDY_abnormal_data['提交时间']).dt.strftime("%Y-%m-%d")
|
|
|
|
thirty_days_ago = (current_date - timedelta(days=30)).strftime("%Y-%m-%d")
|
|
|
|
final_JDY_abnormal_data = latest_JDY_abnormal_data[latest_JDY_abnormal_data['提交时间'] > thirty_days_ago] # 筛选出提交时间为近30天的数据
|
|
|
|
# final_JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_最新数据.xlsx'), index=False)
|
|
|
|
df_abnormal_data = df_abnormal_data[~df_abnormal_data['账号'].isin(final_JDY_abnormal_data['账号'])]
|
|
# empty_num = df_abnormal_data['手机号'].isnull().sum()
|
|
df_abnormal_data = df_abnormal_data[df_abnormal_data["联系手机号"] != "None"]
|
|
# df_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_派发数据.xlsx'), index=False)
|
|
|
|
self.send_request(df_abnormal_data)
|
|
common_module.send_task_status(task_start_time, "接车宝异常派发")
|
|
|
|
|
|
# df_abnormal_data = [self.row_to_dict(row, self.field_mapping) for index, row in
|
|
# df_abnormal_data.iterrows()]
|
|
#
|
|
# data = {'api_key': Config.EFFICIENT_CAR_PICKUP_APP_ID, 'entry_id':"67174710da507490d8ac12c1",
|
|
# "data_list": df_abnormal_data}
|
|
#
|
|
#
|
|
# result = api_instance.entry_data_batch_create(data)
|
|
|
|
@staticmethod
|
|
def row_to_dict(row, field_mapping):
|
|
"""将一行数据转换为指定格式的字典"""
|
|
result = {}
|
|
# print(field_mapping)
|
|
for col_name, widget_id in field_mapping.items():
|
|
# print(col_name, widget_id)
|
|
if col_name in row:
|
|
value = row[col_name]
|
|
clean_value = None if pd.isna(value) else value
|
|
result[widget_id] = {"value": clean_value}
|
|
return result
|
|
|
|
def fields(self):
|
|
self.field_mapping = {"日期": "_widget_1739252804406", "产品名称": "_widget_1739252804397",
|
|
"账号": "_widget_1739258942667", "联系手机号": "_widget_1739252804407",
|
|
"使用时长": "_widget_1739252804409", "开户日": "_widget_1739252804396",
|
|
"到期日": "_widget_1739252804408", "续约日": "_widget_1739252804410",
|
|
"客户状态": "_widget_1739252804400", "近一周开单量": "_widget_1739252804413",
|
|
"近一周是否活跃": "_widget_1739252804414",
|
|
"G状态:近30天开单大于等于10天": "_widget_1739252804415",
|
|
"当月开单天数": "_widget_1739252804416", "近30天开单天数": "_widget_1739252804417",
|
|
"当月G天数": "_widget_1739252804418", "日分区": "_widget_1739252804419",
|
|
"表单类型": "_widget_1739951204545", "派发日期": "_widget_1740036367181",
|
|
"跟进人": "_widget_1740043340255",
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
start = JCBAbnormalRevisit()
|
|
start.main()
|
|
# if result is not None:
|
|
# print(result.head()) # 打印前几行数据
|