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()) # 打印前几行数据