{ "cells": [ { "cell_type": "code", "id": "initial_id", "metadata": { "collapsed": true, "jupyter": { "is_executing": true }, "ExecuteTime": { "start_time": "2025-06-19T03:11:41.874106Z" } }, "source": [ "import os\n", "import time\n", "import requests\n", "import pandas as pd\n", "import datetime\n", "import re\n", "from api import API\n", "from back_ground_module import CommonModule\n", "from log_config import configure_task_logger, configure_error_task_logger\n", "\n", "api_instance = API()\n", "common_module = CommonModule()\n", "logger = configure_task_logger()\n", "error_task_logger = configure_error_task_logger()\n", "\n", "\n", "class RenewServicesRevisit:\n", " \"\"\"用于处理续约服务回访的类。\"\"\"\n", "\n", " def __init__(self):\n", " # 初始化所有数据属性\n", " self.index = None\n", " self.data_NGV = None\n", " self.date_list = None\n", " self.Smart_detection = None\n", " self.service_remind = None\n", " self.json_list = []\n", " self.NGV_data_list = None\n", " self.permissions_table = None\n", " self.staff_id_list = None\n", " self.get_feature_usage = None\n", " self.policy_recognition = None\n", " self.widget_list = None\n", " self.private_domain = None\n", " self.public_domain = None\n", " self.public_domain_list = None\n", " self.different_industries = None\n", " self.different_industries_list = None\n", " self.groupnotification = None\n", " self.date_one = None\n", " self.all_data = []\n", "\n", " def calculate_date_one(self, start_offset=0):\n", " \"\"\"\n", " 计算从当前日期(或指定偏移量的日期)开始,往前遍历遇到date_list中日期的次数。\n", "\n", " 参数:\n", " - start_offset: 从当前日期起始的天数偏移量,默认为0(即今天)。负数表示过去,正数表示未来。\n", "\n", " 返回:\n", " - date_one: 遍历到date_list中日期的次数。\n", " \"\"\"\n", " now_time = datetime.datetime.now() + datetime.timedelta(days=start_offset)\n", " date_one = 1\n", " logger.info(f\"当前日期:{now_time.strftime('%Y-%m-%d')}\")\n", "\n", " if now_time.strftime(\"%Y-%m-%d\") in self.date_list:\n", " date_one = 0\n", " logger.info(f\"开始次数:{date_one}\")\n", " else:\n", " for i in range(1, 10):\n", " new_date = now_time + datetime.timedelta(days=-i)\n", " new_date_str = new_date.strftime(\"%Y-%m-%d\")\n", " if new_date_str in self.date_list:\n", " date_one += 1\n", " logger.info(f\"节假日期:{new_date_str}\")\n", " else:\n", " break\n", " logger.info(f\"遍历次数:{date_one}\")\n", " return date_one\n", "\n", " @staticmethod\n", " def download_url_content(url, save_path):\n", " \"\"\"下载指定URL的内容并保存到本地文件。\"\"\"\n", " try:\n", " response = requests.get(url, stream=True)\n", " response.raise_for_status()\n", " os.makedirs(os.path.dirname(save_path), exist_ok=True)\n", " with open(save_path, 'wb') as file:\n", " for chunk in response.iter_content(chunk_size=8192):\n", " if chunk:\n", " file.write(chunk)\n", " logger.info(f\"文件已成功保存到 {save_path}\")\n", " except requests.exceptions.RequestException as e:\n", " logger.error(f\"下载失败: {e}\")\n", " except Exception as e:\n", " logger.error(f\"发生错误: {e}\")\n", "\n", " def load_all_data(self):\n", " \"\"\"加载所有必要的数据表\"\"\"\n", " # 省市区人员关系表\n", " payload = {\"api_key\": \"675b900991ad2491c69389ca\", \"entry_id\": \"676512ac3e54dc3159460c0a\"}\n", " self.json_list = api_instance.entry_data_list(payload).get(\"data\", [])\n", "\n", " # 获取简道云员工id\n", " payload = {\"api_key\": \"6694d3c4fcb69ca9a111a6c4\", \"entry_id\": \"6769204a1902c9341340a1bc\"}\n", " self.staff_id_list = api_instance.entry_data_list(payload).get(\"data\", [])\n", "\n", " # 获取权限表信息\n", " payload = {\"api_key\": \"675b900991ad2491c69389ca\", \"entry_id\": \"675b96c14e839f90fef1647c\"}\n", " self.permissions_table = api_instance.entry_data_list(payload).get(\"data\", [])\n", "\n", " # 获取NGV数据\n", " payload = {\"api_key\": \"675b900991ad2491c69389ca\", \"entry_id\": \"675bb02bd2d53c2034c665e4\"}\n", " self.NGV_data_list = api_instance.entry_data_list(payload).get(\"data\", [])\n", "\n", " # 其他数据表加载...\n", " # [此处保持原有数据加载逻辑不变]\n", "\n", " @staticmethod\n", " def build_index(json_list):\n", " \"\"\"构建省市区人员索引\"\"\"\n", " index = {}\n", " for json_item in json_list:\n", " try:\n", " key = (json_item['_widget_1734677164861'],\n", " json_item['_widget_1734677164862'],\n", " json_item['_widget_1734677164863'])\n", " if '_widget_1734677164871' not in json_item:\n", " raise KeyError(\"缺少'日常回访客服'键\")\n", " index[key] = json_item\n", " except KeyError as e:\n", " logger.warning(f\"{e},跳过该条记录: {json_item}\")\n", " continue\n", " return index\n", "\n", " @staticmethod\n", " def find_customer_service(province_name, city_name, area_name, index):\n", " \"\"\"根据省市区查找客服\"\"\"\n", " key = (province_name, city_name, area_name)\n", " return index.get(key, \"数据缺失: 未找到对应的日常回访客服\")\n", "\n", " @staticmethod\n", " def get_staff_id(row_item, name):\n", " \"\"\"根据姓名获取员工ID\"\"\"\n", " if str(row_item[\"_widget_1734942794144\"]) == str(name):\n", " return row_item[\"_widget_1734942794145\"]\n", " return None\n", "\n", " def assign_customer_service(self, province_name, city_name, area_name, index):\n", " \"\"\"根据省市区派发给日常回访客服\"\"\"\n", " try:\n", " customer_service_info = self.find_customer_service(province_name, city_name, area_name, index)\n", "\n", " def safe_get_username(data, key):\n", " if isinstance(data, dict):\n", " return data.get(key, {}).get('username', \"\")\n", " return \"\"\n", "\n", " relationship_manager = safe_get_username(customer_service_info, '_widget_1734677164864')\n", " customer_service = safe_get_username(customer_service_info, '_widget_1734677164871')\n", " technician = safe_get_username(customer_service_info, '_widget_1734677164866')\n", " area_manager = safe_get_username(customer_service_info, '_widget_1734677164865')\n", " return relationship_manager, customer_service, technician, area_manager\n", " except Exception as e:\n", " logger.error(f\"Error finding customer service: {e}\")\n", " return \"分配失败,请检查\", \"分配失败,请检查\", \"分配失败,请检查\"\n", "\n", " def prepare_data(self):\n", " \"\"\"准备基础数据\"\"\"\n", " # Step 1: 加载所有数据表\n", " self.load_all_data()\n", "\n", " # Step 2: 获取节假日列表\n", " self.date_list = common_module.get_holiday_list()\n", "\n", " # Step 3: 获取NGV数据\n", " self.data_NGV = common_module.get_ngv_details(days_back=1).astype(str)\n", "\n", " # Step 4: 计算日期偏移\n", " self.date_one = self.calculate_date_one(start_offset=0)\n", "\n", " # Step 5: 构建索引\n", " self.index = self.build_index(self.json_list)\n", "\n", " logger.info(\"数据准备完成\")\n", "\n", " def filter_and_process_data(self):\n", " \"\"\"过滤和处理数据\"\"\"\n", " # Step 1: 准备数据\n", " self.prepare_data()\n", "\n", " logger.info(\"开始运行主流程\")\n", "\n", " # 获取原始NGV数据\n", " data_NGV = self.data_NGV.copy()\n", " # 数据清洗\n", " data_NGV = data_NGV.apply(lambda series: series.apply(\n", " lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x))\n", " \n", " # 日期列转换\n", " data_NGV['A'] = pd.to_datetime(data_NGV['expiry_time'])\n", " data_NGV['B'] = pd.to_datetime(data_NGV['renew_date'])\n", " \n", "\n", " # 定义优先级顺序\n", " edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']\n", " customer_type_order = [\"F\", \"E\", \"D\", \"C\", \"B\", \"A\"]\n", " group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']\n", "\n", " # 创建映射字典\n", " edition_map = {edition: idx for idx, edition in enumerate(edition_order)}\n", " customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}\n", " group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}\n", "\n", " # 添加排序列\n", " data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(int)\n", " data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(int)\n", " data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)\n", "\n", " # 找到最佳值\n", " best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()\n", " best_edition_rows = data_NGV.loc[best_edition_idx]\n", " best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']\n", "\n", " best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()\n", " best_customer_type_rows = data_NGV.loc[best_customer_type_idx]\n", " best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(\n", " lambda x: customer_type_order[x])\n", "\n", " best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()\n", " best_group_grade_rows = data_NGV.loc[best_group_grade_idx]\n", " best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']\n", "\n", " # 合并最佳值\n", " best_values = (\n", " best_edition_rows[['id_own_group', 'max_saas_edition']]\n", " .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group', how='outer')\n", " .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')\n", " )\n", " data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')\n", "\n", " # 主店过期过滤\n", " condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件\n", "\n", " ngvv2 = data_NGV[condition]\n", "\n", " data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中\n", " data_NGV_V2['条件'] = ((data_NGV_V2['org_type'] == \"一般\") & (data_NGV_V2['org_status'] == '留存') &\n", " (data_NGV_V2['area_manager'] != '殷昊') & (data_NGV_V2['area_manager'] != '孙玉蕾') & (data_NGV_V2['is_main_org'] != 1))\n", " data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2[\"条件\"]]\n", " # 步骤4: 过滤存在的记录\n", " data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])\n", " filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]\n", "\n", " fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']\n", " # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))\n", "\n", " fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}\n", " filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)\n", " filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)\n", "\n", " result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')\n", "\n", " data_NGV['条件'] = (data_NGV['org_type'] == \"一般\") & (data_NGV['org_status'] == '留存') & (\n", " data_NGV['area_manager'] != '殷昊') & (\n", " data_NGV['area_manager'] != '孙玉蕾') & (\n", " data_NGV['is_main_org'] == 1)\n", " data_NGV = pd.concat([data_NGV, result], axis=0)\n", " # data_NGV.to_csv(\"dayin1.csv\")\n", " data_details = data_NGV.copy()\n", " # data_details.to_excel(r\"C:\\Users\\admin\\Downloads\\1.xlsx\")\n", "\n", " # 重置索引\n", " data_details = data_details.reset_index(drop=True)\n", " # data_details.to_csv(\"dayin.csv\")\n", " # 判断A列的日期是否大于B列的日期730天,如果是的话,将B列的值设置为1\n", " data_details['条件'] = data_details.apply(\n", " lambda row: (\n", " (pd.to_datetime(row['A']) - pd.to_datetime(row['B'])).days\n", " if pd.to_datetime(row['A']) - pd.to_datetime(row['B']) >= pd.Timedelta(days=730)\n", " else 0\n", " ),\n", " axis=1\n", " )\n", " data_details = data_details.loc[data_details[\"条件\"] > 0]\n", "\n", "\n", " # 定义一个函数,用于将数字除以365并取整数\n", " def divide_by_365(x):\n", " if isinstance(x, (int, float)):\n", " return int(x / 365)\n", " else:\n", " return x\n", "\n", " # 使用applymap()函数将divide_by_365函数应用到DataFrame的每个元素\n", " data_details['年'] = data_details['条件'].apply(divide_by_365)\n", " # 重置索引\n", " data_details = data_details.reset_index(drop=True)\n", " # data_details.to_excel(r\"C:\\Users\\admin\\Downloads\\2.xlsx\")\n", " # 创建一个新的空的DataFrame\n", " new_df = pd.DataFrame()\n", " # 遍历原始DataFrame的每一行\n", " from datetime import datetime\n", " for index, row in data_details.iterrows():\n", " # 根据A列的值来决定复制的次数\n", " if row[\"renew_date\"] != \"2024-02-29\":\n", " for i_new in range(1, row['年']):\n", " # 修改日期\n", " row_new = row.copy()\n", " c = row_new[\"renew_date\"]\n", " date_obj = datetime.strptime(c, \"%Y-%m-%d\")\n", " new_year = date_obj.year + i_new\n", " new_date_obj = date_obj.replace(year=new_year)\n", " new_c = new_date_obj.strftime(\"%Y-%m-%d\")\n", " row_new[\"renew_date\"] = new_c\n", " # 将当前行添加到新的DataFrame中\n", " # new_df = new_df.append(row_new, ignore_index=True)\n", " new_df = pd.concat([new_df, pd.DataFrame([row_new])], ignore_index=True)\n", " # 合并两个DataFrame\n", " # new_df.to_excel(r\"C:\\Users\\admin\\Downloads\\3.xlsx\")\n", " merged_df = pd.concat([data_NGV, new_df], axis=0, ignore_index=True)\n", " data_details = merged_df.copy() # 替换名称\n", "\n", " data_details_not_null = data_details[data_details['renew_date'].notnull()]\n", " # data_details_not_null = data_details_not_null[data_details_not_null['renew_date'].str.contains('2023')]\n", " # data_details_not_null = data_details_not_null.sort_values(by='renew_date', ascending=True).drop_duplicates(\n", " # subset='id_own_group') 重置索引\n", " data_details_not_null = data_details_not_null.reset_index(drop=True)\n", " data_details = data_details_not_null.copy() # 替换名称 v2\n", " data_details['saas_create_time'] = data_details['saas_create_time'].str[:4] # 截取前10位\n", " data_details['renew_date_new'] = data_details['renew_date'].str[:4] # 截取前10位\n", " data_details = data_details[\n", " data_details['saas_create_time'] != data_details['renew_date_new']] # 过滤掉等于renew_date的行\n", "\n", " data_details = data_details.reset_index(drop=True)\n", "\n", "\n", " import datetime\n", " start_time = datetime.datetime.now()\n", "\n", " date_90 = 83\n", " date_120 = 113\n", " date_180 = 173\n", " # self.date_one = 1\n", " now_time = start_time.replace()\n", "\n", " if now_time.strftime(\"%Y-%m-%d\") in self.date_list:\n", " self.date_one = 0\n", " print(\"开始次数:\", self.date_one)\n", " print(\"当前日期:\", now_time)\n", "\n", " # 处理每个日期偏移\n", " for i in range(0, self.date_one):\n", " print(f\"这是第{i}次遍历\")\n", " import datetime\n", " now_time = datetime.datetime.now() + datetime.timedelta(days=-(i + 1))\n", "\n", " today = now_time + datetime.timedelta(days=-date_90)\n", " formatted_today_90 = today.strftime(\"%Y-%m-%d\")\n", " today = now_time + datetime.timedelta(days=-date_120)\n", " formatted_today_120 = today.strftime(\"%Y-%m-%d\")\n", " today = now_time + datetime.timedelta(days=-date_180)\n", " formatted_today_180 = today.strftime(\"%Y-%m-%d\")\n", " # print(formatted_today_90, formatted_today_120, formatted_today_180)\n", " logger.info(f\"续约回访日期:{formatted_today_90},{formatted_today_180}\")\n", "\n", " # 过滤90天回访记录\n", " data_details_90 = data_details.copy()\n", " data_details_90['条件'] = (\n", " (data_details_90['renew_date'] == formatted_today_90) &\n", " (data_details_90['group_grade'] != \"普通客户(VIP)\"))\n", " data_details_90 = data_details_90.loc[data_details_90[\"条件\"]]\n", " data_details_90[\"跟进阶段\"] = \"续约后90天回访\"\n", " data_details_90[\"主要目的\"] = \"关怀使用情况,促进更多功能使用,提升系统使用深度。\"\n", "\n", " # 过滤180天回访记录\n", " data_details_180 = data_details.copy()\n", " data_details_180['条件'] = (data_details_180['renew_date'] == formatted_today_180)\n", " data_details_180 = data_details_180.loc[data_details_180[\"条件\"]]\n", " data_details_180[\"跟进阶段\"] = \"续约后180天回访\"\n", " data_details_180[\"主要目的\"] = \"关怀使用情况,促进增购商机转化,识别潜在风险,及时提报。\"\n", "\n", " # 合并回访记录(排除120天回访)\n", " data_result = pd.concat([data_details_90, data_details_180], ignore_index=True)\n", " logger.info(f\"续约回访人数:{len(data_result)}\")\n", "\n", " # 处理每个门店数据\n", " self.process_shop_data(data_result)\n", "\n", " def process_shop_data(self, data_NGV):\n", " \"\"\"处理每个门店的数据\"\"\"\n", "\n", " for index_num, row in data_NGV.iterrows():\n", " try:\n", " payload_dict = {}\n", " saas_use_year = re.findall(r'第([0-9]+)年', row[\"saas_use_year\"])[0]\n", "\n", " # 获取员工ID\n", " NGV_roles = {\n", " 'relationship_manager': row['service_impl_principal'],\n", " 'area_manager': row['area_manager'],\n", " 'technician': row['technician'],\n", " 'salesmen': row['salesmen'],\n", " }\n", "\n", " for role, name in NGV_roles.items():\n", " for row_item in self.staff_id_list:\n", " staff_id = self.get_staff_id(row_item, name)\n", " if staff_id:\n", " NGV_roles[role] = staff_id\n", " break\n", " else:\n", " NGV_roles[role] = None\n", "\n", " # 分配回访人员\n", " if int(saas_use_year) < 4:\n", " relationship_manager, area_manager, technician, salesmen = [\n", " NGV_roles[role] for role in ['relationship_manager', 'area_manager', 'technician', 'salesmen']\n", " ]\n", "\n", " if not relationship_manager or not technician:\n", " relationship_manager, _, technician, _ = self.assign_customer_service(\n", " row['province_name'], row['city_name'], row['area_name'], self.index\n", " )\n", "\n", " if row[\"group_grade\"] in [\"普通客户(VIP)\", \"重要客户(SVIP)\"]:\n", " payload_dict[\"_widget_1734590278288\"] = {\"value\": relationship_manager}\n", " else:\n", " payload_dict[\"_widget_1734590278288\"] = {\"value\": technician}\n", " else:\n", " salesmen = NGV_roles['salesmen']\n", " relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(\n", " row['province_name'], row['city_name'], row['area_name'], self.index\n", " )\n", "\n", " if row[\"group_grade\"] in [\"普通客户(VIP)\", \"重要客户(SVIP)\"]:\n", " payload_dict[\"_widget_1734590278288\"] = {\"value\": customer_service}\n", " else:\n", " payload_dict[\"_widget_1734590278288\"] = {\"value\": technician}\n", "\n", " # 其他成员字段赋值\n", " payload_dict.update({\n", " \"_widget_1734590278289\": {\"value\": relationship_manager},\n", " \"_widget_1734590278290\": {\"value\": area_manager},\n", " \"_widget_1734590278291\": {\"value\": technician},\n", " \"_widget_1735290738545\": {\"value\": salesmen}\n", " })\n", "\n", " # 特殊逻辑处理\n", " if payload_dict.get(\"_widget_1734590278288\") == \"02414917880947\":\n", " payload_dict[\"_widget_1734590278288\"] = {\"value\": \"051612246035720178\"}\n", "\n", " # 获取权限信息\n", " group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])\n", " if not row['saas_customer_type'] or row['saas_customer_type'] in ['NA', 'None']:\n", " row['saas_customer_type'] = \"F\"\n", "\n", " NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']\n", " logger.info(f\"权限唯一值:{NGV_store_level_key}\")\n", "\n", " # 处理权限表逻辑\n", " Billing = None\n", " for item in self.permissions_table:\n", " if NGV_store_level_key == item.get(\"_widget_1734056507963\"): # 合并(等级-类型-分层)\n", " print(\"该门店开单的权限是:\", item.get(\"_widget_1734055617039\"))\n", " Billing = item.get(\"_widget_1734055617039\") # 开单\n", " Service_Alerts = item.get(\"_widget_1734055617040\") # 服务提醒\n", " membership = item.get(\"_widget_1734055617041\") # 会员卡\n", " SMS = item.get(\"_widget_1734055617042\") # 短信\n", " Public_domain_applets = item.get(\"_widget_1734055617043\") # 公域小程序\n", " Private_domain_applets = item.get(\"_widget_1734055617044\") # 私域小程序\n", " Test_sheet = item.get(\"_widget_1734055617045\") # 检测单\n", " AI_poster = item.get(\"_widget_1734055617046\") # AI海报\n", " Business_wallets = item.get(\"_widget_1734055617047\") # 企业钱包\n", " Precision_marketing = item.get(\"_widget_1734055617049\") # 精准营销\n", " Paid_memberships = item.get(\"_widget_1734055617051\") # 付费会员\n", " business_WeCom = item.get(\"_widget_1734055617052\") # 企业微信\n", " Insurance_policy_identification = item.get(\"_widget_1734055617053\") # 保险单识别\n", " Insurance_bots = item.get(\"_widget_1734055617054\") # 保险机器人\n", " Camera_pick_up = item.get(\"_widget_1734055617055\") # 摄像头接车\n", " Camera_billing = item.get(\"_widget_1734055617056\") # 摄像头开单\n", " Transparent_workshop = item.get(\"_widget_1734055617057\") # 透明车间\n", " Cross_industry_cooperation = item.get(\"_widget_1734055617058\") # 异业合作\n", " BI_Insights = item.get(\"_widget_1734055617059\") # BI洞察\n", " payload_dict.update(\n", " {\n", " \"_widget_1734073342350\": {\"value\": Billing},\n", " \"_widget_1735004315757\": {\"value\": Service_Alerts},\n", " \"_widget_1735004315756\": {\"value\": membership},\n", " \"_widget_1735004315755\": {\"value\": SMS},\n", " \"_widget_1735004315754\": {\"value\": Public_domain_applets},\n", " \"_widget_1735004315753\": {\"value\": Private_domain_applets},\n", " \"_widget_1735004315752\": {\"value\": Test_sheet},\n", " \"_widget_1735004315751\": {\"value\": AI_poster},\n", " \"_widget_1735004315750\": {\"value\": Business_wallets},\n", " \"_widget_1735004315749\": {\"value\": Precision_marketing},\n", " \"_widget_1735004315748\": {\"value\": Paid_memberships},\n", " \"_widget_1735004315747\": {\"value\": business_WeCom},\n", " \"_widget_1735004315746\": {\"value\": Insurance_policy_identification},\n", " \"_widget_1735004315745\": {\"value\": Insurance_bots},\n", " \"_widget_1735004315744\": {\"value\": Camera_pick_up},\n", " \"_widget_1735004315743\": {\"value\": Camera_billing},\n", " \"_widget_1735004315742\": {\"value\": Transparent_workshop},\n", " \"_widget_1735004315741\": {\"value\": Cross_industry_cooperation},\n", " \"_widget_1734073342352\": {\"value\": BI_Insights},\n", "\n", " }\n", " )\n", "\n", " feature_dict = {\n", " \"开单\": \"_widget_1734073342350\",\n", " \"服务提醒\": \"_widget_1735004315757\",\n", " \"会员卡\": \"_widget_1735004315756\",\n", " \"短信\": \"_widget_1735004315755\",\n", " \"公域小程序\": \"_widget_1735004315754\",\n", " \"私域小程序\": \"_widget_1735004315753\",\n", " \"检测单\": \"_widget_1735004315752\",\n", " \"AI海报\": \"_widget_1735004315751\",\n", " \"企业钱包\": \"_widget_1735004315750\",\n", " \"精准营销\": \"_widget_1735004315749\",\n", " \"付费会员\": \"_widget_1735004315748\",\n", " \"企业微信\": \"_widget_1735004315747\",\n", " \"保险单识别\": \"_widget_1735004315746\",\n", " \"保险机器人\": \"_widget_1735004315745\",\n", " \"摄像头接车\": \"_widget_1735004315744\",\n", " \"摄像头开单\": \"_widget_1735004315743\",\n", " \"透明车间\": \"_widget_1735004315742\",\n", " \"异业合作\": \"_widget_1735004315741\",\n", " \"BI洞察\": \"_widget_1734073342352\",\n", "\n", " }\n", " # _widget_1735527329557 下次是否推荐\n", " for new_item in self.get_feature_usage:\n", " for feature_module, feature_value in feature_dict.items(): # 模块\n", " if new_item.get(\"_widget_1735268263079\") == feature_module and new_item.get(\n", " \"_widget_1735527329557\") == \"否\" and new_item.get(\n", " \"_widget_1735280720550\") == \\\n", " row[\"id_own_org\"]: # 下次是否推荐 功能使用情况表\n", " print(f\"{feature_value}进行了更改\")\n", " payload_dict.update({f\"{feature_value}\": {\"value\": \"×\"}})\n", "\n", " if new_item.get(\"_widget_1735268263079\") == feature_module and new_item.get(\n", " \"_widget_1736414617462\") == \"否\" and new_item.get(\n", " \"_widget_1735280720550\") == \\\n", " row[\"id_own_org\"]: # 下次是否跟进\n", " print(f\"{feature_value}进行了更改\")\n", " payload_dict.update({f\"{feature_value}\": {\"value\": \"×\"}})\n", "\n", " fields_to_check = {\n", " \"_widget_1735004315763\": Billing, # 开单\n", " \"_widget_1735106258016\": Service_Alerts, # 服务提醒\n", " \"_widget_1735106258036\": membership, # 会员卡\n", " \"_widget_1735106258086\": SMS, # 短信\n", " \"_widget_1735106258112\": Public_domain_applets, # 公域小程序\n", " \"_widget_1735106258141\": Private_domain_applets, # 私域小程序\n", " \"_widget_1735107354648\": Test_sheet, # 检测单\n", " \"_widget_1735107354725\": AI_poster, # AI海报\n", " \"_widget_1735107354811\": Business_wallets, # 企业钱包\n", " \"_widget_1735107354906\": Precision_marketing, # 精准营销\n", " \"_widget_1735107354980\": Paid_memberships, # 付费会员\n", " \"_widget_1735107355093\": business_WeCom, # 企业微信\n", " \"_widget_1735107355143\": Insurance_policy_identification, # 保险单识别\n", " \"_widget_1735107355235\": Insurance_bots, # 保险机器人\n", " \"_widget_1735107355333\": Camera_pick_up, # 摄像头接车\n", " \"_widget_1735107355392\": Camera_billing, # 摄像头开单\n", " \"_widget_1735107355502\": Transparent_workshop, # 透明车间\n", " \"_widget_1735107355618\": Cross_industry_cooperation, # 异业合作\n", " \"_widget_1735107355740\": BI_Insights # BI洞察\n", " }\n", "\n", " # 遍历每个字段,检查其值并更新payload_dict\n", " for widget_id, field_name in fields_to_check.items():\n", " if field_name == \"√\":\n", " payload_dict.update({widget_id: {\"value\": \"是\"}})\n", "\n", " break\n", "\n", " if not Billing:\n", " print(f\"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}\")\n", " \n", " # 使用情况\n", " if row[\"active_status_fmt\"] == \"活跃\": # 开单 是否使用\n", " payload_dict.update({\"_widget_1735004315765\": {\"value\": \"是\"}})\n", " else:\n", " payload_dict.update({\"_widget_1735004315765\": {\"value\": \"否\"}})\n", " try:\n", " if row[\"saas_edition_fmt\"] not in [\"基础版\", \"入门版\"]: # 会员卡 是否拥有\n", " payload_dict.update({\"_widget_1735106258036\": {\"value\": \"是\"}})\n", " else:\n", " payload_dict.update({\"_widget_1735106258036\": {\"value\": \"否\"}})\n", " except Exception as e:\n", " print(f\"会员卡识别:Error finding customer service: {e}\")\n", " try:\n", " if row[\"card_bill_day_count_last_30_day\"] != \"0\": # 会员卡 是否使用\n", " payload_dict.update({\"_widget_1735106258038\": {\"value\": \"是\"}})\n", " else:\n", " payload_dict.update({\"_widget_1735106258038\": {\"value\": \"否\"}})\n", " except Exception as e:\n", " print(f\"会员卡识别:Error finding customer service: {e}\")\n", " # print(self.service_remind.get(\"_widget_1735112637045\"))\n", " payload_dict[\"_widget_1735106258018\"] = {\"value\": \"否\"}\n", "\n", " for item in self.service_remind:\n", " if row[\"id_own_group\"] == item.get(\"_widget_1735112637043\"):\n", " if int(item.get(\"_widget_1735112637045\")) < 180 and int(\n", " item.get(\"_widget_1735112637046\")) == 1: # 服务提醒 是否使用\n", " payload_dict.update({\"_widget_1735106258018\": {\"value\": \"是\"}})\n", " break\n", " elif int(item.get(\"_widget_1735112637048\")) > 0:\n", " payload_dict.update({\"_widget_1735106258018\": {\"value\": \"是\"}})\n", " break\n", "\n", " keys_to_check = [\n", " \"_widget_1735113110155\"\n", " ] # 智能检测 是否使用\n", "\n", " # 初始化默认值为\"否\"\n", " payload_dict[\"_widget_1735107354650\"] = {\"value\": \"否\"}\n", "\n", " # 检查每个键,如果有一个大于0,则更新为\"是\"并停止检查\n", " for key in keys_to_check:\n", " for item in self.Smart_detection:\n", " if row[\"id_own_org\"] == item.get(\"_widget_1735113110147\"):\n", " if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况\n", " payload_dict[\"_widget_1735107354650\"][\"value\"] = \"是\"\n", " break\n", "\n", " # 近30天业务单量=0 则其它所有模块均不推荐\n", " try:\n", " for feature_module, feature_value in feature_dict.items(): # 模块\n", " if row[\"bill_count_last_30_day\"] == '0' and payload_dict[feature_value][\"value\"] == '△':\n", " payload_dict.update({f\"{feature_value}\": {\"value\": \"×\"}})\n", " except Exception as e:\n", " print(f\"不开单识别:Error finding customer service: {e}\")\n", " # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐\n", " try:\n", " if row[\"org_code\"] in self.widget_list:\n", " payload_dict.update({'_widget_1735004315746': {\"value\": \"△\"}})\n", " except Exception as e:\n", " print(f\"保单识别:Error finding customer service: {e}\")\n", "\n", " # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有\n", " try:\n", " for item in self.private_domain:\n", " if row[\"id_own_group\"] == item.get(\"_widget_1742795002375\"): # 公司id\n", " if int(item.get(\"_widget_1742795002379\")) > 0: # 上架商品数\n", " payload_dict.update({\"_widget_1735106258143\": {\"value\": \"是\"}}) # DX:是否拥有\n", " break\n", " else:\n", " payload_dict.update({\"_widget_1735106258143\": {\"value\": \"否\"}}) # DX:是否拥有\n", " break\n", " except Exception as e:\n", " print(f\"私域小程序:Error finding customer service: {e}\")\n", " try:\n", " high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']\n", " if row[\"saas_edition_fmt\"] in high_version:\n", " payload_dict.update({'_widget_1735106258141': {\"value\": \"是\"}}) # SYXCX:是否拥有\n", " else:\n", " payload_dict.update({'_widget_1735106258141': {\"value\": \"否\"}}) # SYXCX:是否拥有\n", " except Exception as e:\n", " print(f\"私域小程序:Error finding customer service: {e}\")\n", "\n", " # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有\n", " try:\n", " for item in self.public_domain:\n", " if row[\"id_own_org\"] == item.get(\"_widget_1742784257506\"): # 门店id\n", " if int(item.get(\"_widget_1742784257509\")) == 1: # 发布商品数量\n", " payload_dict.update({\"_widget_1735106258114\": {\"value\": \"是\"}}) # GYXCX:是否使用\n", " break\n", " else:\n", " payload_dict.update({\"_widget_1735106258114\": {\"value\": \"否\"}}) # GYXCX:是否使用\n", " break\n", " except Exception as e:\n", " print(f\"公域小程序:Error finding customer service: {e}\")\n", " try:\n", " if row[\"id_own_org\"] in self.public_domain_list:\n", " payload_dict.update({'_widget_1735106258112': {\"value\": \"是\"}}) # GYXCX:是否拥有\n", " else:\n", " payload_dict.update({'_widget_1735106258112': {\"value\": \"否\"}}) # GYXCX:是否拥有\n", " except Exception as e:\n", " print(f\"公域小程序:Error finding customer service: {e}\")\n", "\n", " # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字\n", " try:\n", " if row[\"id_own_org\"] in self.different_industries_list:\n", " payload_dict.update({'_widget_1735107355618': {\"value\": \"是\"}}) # YYHZ:是否拥有\n", " else:\n", " payload_dict.update({'_widget_1735107355618': {\"value\": \"否\"}}) # YYHZ:是否拥有\n", " except Exception as e:\n", " print(f\"异业合作:Error finding customer service: {e}\")\n", "\n", " # 短信:根据是否启动短信功能判断是否拥有,根据\n", " try:\n", " for item in self.groupnotification:\n", " if row[\"id_own_group\"] == item.get(\"_widget_1743065201885\"): # 公司id\n", " if int(item.get(\"_widget_1743065201886\")) == 1: # 是否启动短信功能\n", " payload_dict.update({\"_widget_1735106258086\": {\"value\": \"是\"}}) # DX:是否拥有\n", " break\n", " else:\n", " payload_dict.update({\"_widget_1735106258086\": {\"value\": \"否\"}}) # DX:是否拥有\n", " break\n", " except Exception as e:\n", " print(f\"短信:Error finding customer service: {e}\")\n", " try:\n", " for item in self.groupnotification:\n", " if row[\"id_own_group\"] == item.get(\"_widget_1743065201885\"): # 公司id\n", " if int(item.get(\"_widget_1743065201889\")) > 0: # 累计发送成功总人数\n", " payload_dict.update({\"_widget_1735106258088\": {\"value\": \"是\"}}) # DX:是否使用\n", " break\n", " else:\n", " payload_dict.update({\"_widget_1735106258088\": {\"value\": \"否\"}}) # DX:是否使用\n", " break\n", " except Exception as e:\n", " print(f\"短信:Error finding customer service: {e}\")\n", " NGV_data_id = None\n", " # 获取关联数据\n", " for NGV_Data in self.NGV_data_list:\n", " # NGV_Data = NGV_Data.get(\"data\")\n", " if row[\"org_code\"] == NGV_Data.get(\"_widget_1734062123071\"): # 门店编码\n", " NGV_data_id = NGV_Data.get(\"_id\")\n", " print(NGV_data_id)\n", " try:\n", " png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', \"\")\n", " except:\n", " png_url = \"\"\n", " print(png_url)\n", " if not NGV_data_id:\n", " print(\"未找到数据ID\")\n", "\n", " distribution_date = datetime.datetime.now(datetime.timezone.utc)\n", " distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'\n", "\n", " upload_key = None\n", " UUid = time.strftime(\"%Y%m%d%H%M%S\", time.localtime())\n", " if png_url:\n", " save_dir = \"sampleCloud\" # 设置输出目录\n", "\n", " # 创建输出目录(如果不存在)\n", " import os\n", "\n", " os.makedirs(save_dir, exist_ok=True)\n", "\n", " save_path = fr'{save_dir}\\png\\{time.strftime(\"%Y%m%d%H%M%S\", time.localtime())}.png'\n", "\n", " RenewServicesRevisit.download_url_content(png_url, save_path)\n", "\n", " up_data = api_instance.get_upload_token(\n", " {\"api_key\": \"675b900991ad2491c69389ca\", \"entry_id\": \"675b9c63925cd404038a6b86\",\n", " \"transaction_id\": UUid})\n", " upload_url = up_data.get(\"upload_url\")\n", " upload_token = up_data.get(\"upload_token\")\n", "\n", " upload_result = api_instance.upload_file(\n", " {\"upload_url\": upload_url, \"upload_token\": upload_token, \"file_path\": save_path})\n", " upload_key = upload_result.get(\"key\")\n", "\n", " payload_dict.update({\n", " \"_widget_1734590278279\": {\"value\": row[\"group_name\"]}, # 公司名称\n", " \"_widget_1735112931760\": {\"value\": row[\"id_own_group\"]}, # 公司id\n", " \"_widget_1735112931761\": {\"value\": row[\"id_own_org\"]}, # 门店id\n", " \"_widget_1734590278281\": {\"value\": row['org_name']}, # 门店名称\n", " \"_widget_1734590278292\": {\"value\": row[\"跟进阶段\"]}, # 跟进阶段\n", " \"_widget_1734321349021\": {\"value\": NGV_data_id}, # 关data_get联数据\n", " \"_widget_1742548684369\": {\"value\": row['主要目的']}, # 主要目的\n", " \"_widget_1734590278266\": {\"value\": row['region_name']}, # 大区\n", " \"_widget_1734590278285\": {\"value\": row['branch_name']}, # 小区\n", " \"_widget_1734590278284\": {\"value\": row['province_name']}, # 省\n", " \"_widget_1734590278283\": {\"value\": row['city_name']}, # 市\n", " \"_widget_1734590278282\": {\"value\": row['area_name']}, # 区\n", " \"_widget_1734590278278\": {\"value\": row['saas_customer_type']}, # 门店分层\n", " \"_widget_1734590278277\": {\"value\": row['group_grade']}, # 公司等级\n", " \"_widget_1734590278276\": {\"value\": row['limit_user_type']}, # 限制账户类型\n", " \"_widget_1734590278275\": {\"value\": row['active_user_type']}, # 有效账户类型\n", " \"_widget_1734590278274\": {\"value\": row['saas_version']}, # ERP操作模式\n", " \"_widget_1734590278273\": {\"value\": row['saas_use_year']}, # 使用时长\n", " \"_widget_1734590278272\": {\"value\": row['org_stage']}, # 门店阶段\n", " \"_widget_1734590278271\": {\"value\": row['manage_model']}, # 经营模式\n", " \"_widget_1734590278267\": {\"value\": row['contacts']}, # 联系人\n", " \"_widget_1734590278287\": {\"value\": row['contact_mobile']}, # 联系手机号\n", " \"_widget_1734590278286\": {\"value\": row['saas_edition_fmt']}, # SaaS版本\n", " \"_widget_1734590278280\": {\"value\": row['org_code']}, # 门店编码\n", " # \"_widget_1735287791875\": {\"value\": row['salesmen']}, # 销售负责人\n", " \"_widget_1735096489244\": {\"value\": distribution_date}, # 派发时间\n", " \"_widget_1742895342914\": {\"value\": row['business_scope_fmt']}, # 经营范围\n", " \"_widget_1742895342915\": {\"value\": row['station_number']}, # 工位数\n", " \"_widget_1742895342916\": {\"value\": [upload_key]} # 门头照片\n", " })\n", "\n", " routine_follow_up_payload = {\n", " \"api_key\": \"675b900991ad2491c69389ca\",\n", " \"entry_id\": \"675b9c63925cd404038a6b86\",\n", " \"is_start_workflow\": \"true\",\n", " \"data\": payload_dict,\n", " \"transaction_id\": UUid\n", " }\n", "\n", " print(routine_follow_up_payload)\n", "\n", " res = api_instance.data_batch_create(routine_follow_up_payload)\n", " logger.info(f\"创建结果:{res}\")\n", " \n", "\n", " except Exception as e:\n", " error_task_logger.error(f\"处理门店数据时出错: {e}\")\n", " continue\n", " \n", "\n", " def main(self):\n", " \"\"\"主入口方法\"\"\"\n", " task_start_time = datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n", " # try:\n", " self.filter_and_process_data()\n", " common_module.send_task_status(task_start_time, \"续约客户回访\")\n", " logger.info(\"任务执行成功\")\n", " # except Exception as e:\n", " # error_task_logger.error(f\"任务执行失败: {e}\")\n", " df = pd.DataFrame(self.all_data)\n", " df.to_csv(\"all_data.csv\")\n", "\n", "\n", "if __name__ == '__main__':\n", " start = RenewServicesRevisit()\n", " start.main()\n" ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "已获取 100 条数据\n", "已获取 200 条数据\n", "已获取 300 条数据\n", "已获取 400 条数据\n", "已获取 500 条数据\n", "已获取 600 条数据\n", "已获取 700 条数据\n", "已获取 800 条数据\n", "已获取 900 条数据\n", "已获取 1000 条数据\n", "已获取 1100 条数据\n", "已获取 1200 条数据\n", "已获取 1300 条数据\n", "已获取 1400 条数据\n", "已获取 1500 条数据\n", "已获取 1600 条数据\n", "已获取 1700 条数据\n", "已获取 1800 条数据\n", "已获取 1900 条数据\n", "已获取 2000 条数据\n", "已获取 2100 条数据\n", "已获取 2200 条数据\n", "已获取 2300 条数据\n", "已获取 2400 条数据\n", "已获取 2500 条数据\n", "已获取 2600 条数据\n", "已获取 2700 条数据\n", "已获取 2800 条数据\n", "已获取 2900 条数据\n", "已获取 3000 条数据\n", "已获取 3100 条数据\n", "已获取 3200 条数据\n", "已获取 3300 条数据\n", "已获取 3400 条数据\n", "已获取 3500 条数据\n", "已获取 3600 条数据\n", "已获取 3667 条数据\n", "已获取 100 条数据\n", "已获取 140 条数据\n", "已获取 100 条数据\n", "已获取 192 条数据\n", "已获取 100 条数据\n", "已获取 200 条数据\n", "已获取 300 条数据\n", "已获取 400 条数据\n", "已获取 500 条数据\n", "已获取 600 条数据\n", "已获取 700 条数据\n", "已获取 800 条数据\n", "已获取 900 条数据\n", "已获取 1000 条数据\n", "已获取 1100 条数据\n", "已获取 1200 条数据\n", "已获取 1300 条数据\n", "已获取 1400 条数据\n", "已获取 1500 条数据\n", "已获取 1600 条数据\n", "已获取 1700 条数据\n", "已获取 1800 条数据\n", "已获取 1900 条数据\n", "已获取 2000 条数据\n", "已获取 2100 条数据\n", "已获取 2200 条数据\n", "已获取 2300 条数据\n", "已获取 2400 条数据\n", "已获取 2500 条数据\n", "已获取 2600 条数据\n", "已获取 2700 条数据\n", "已获取 2800 条数据\n", "已获取 2900 条数据\n", "已获取 3000 条数据\n", "已获取 3100 条数据\n", "已获取 3200 条数据\n", "已获取 3300 条数据\n", "已获取 3400 条数据\n", "已获取 3500 条数据\n", "已获取 3600 条数据\n", "已获取 3700 条数据\n", "已获取 3800 条数据\n", "已获取 3900 条数据\n", "已获取 4000 条数据\n", "已获取 4100 条数据\n", "已获取 4200 条数据\n", "已获取 4300 条数据\n", "已获取 4400 条数据\n", "已获取 4500 条数据\n", "已获取 4600 条数据\n", "已获取 4700 条数据\n", "已获取 4800 条数据\n", "已获取 4900 条数据\n", "已获取 5000 条数据\n", "已获取 5100 条数据\n", "已获取 5200 条数据\n", "已获取 5300 条数据\n", "已获取 5400 条数据\n", "已获取 5500 条数据\n", "已获取 5600 条数据\n", "已获取 5700 条数据\n", "已获取 5800 条数据\n", "已获取 5900 条数据\n", "已获取 6000 条数据\n", "已获取 6100 条数据\n", "已获取 6200 条数据\n", "已获取 6300 条数据\n", "已获取 6400 条数据\n", "已获取 6500 条数据\n", "已获取 6600 条数据\n", "已获取 6700 条数据\n", "已获取 6800 条数据\n", "已获取 6900 条数据\n", "已获取 7000 条数据\n", "已获取 7100 条数据\n", "已获取 7200 条数据\n", "已获取 7300 条数据\n", "已获取 7400 条数据\n", "已获取 7500 条数据\n", "已获取 7600 条数据\n", "已获取 7700 条数据\n", "已获取 7800 条数据\n", "已获取 7900 条数据\n", "已获取 8000 条数据\n", "已获取 8100 条数据\n", "已获取 8200 条数据\n", "已获取 8300 条数据\n", "已获取 8400 条数据\n", "已获取 8500 条数据\n", "已获取 8600 条数据\n", "已获取 8700 条数据\n", "已获取 8800 条数据\n", "已获取 8900 条数据\n", "已获取 9000 条数据\n", "已获取 9100 条数据\n", "已获取 9200 条数据\n", "已获取 9300 条数据\n", "已获取 9400 条数据\n", "已获取 9500 条数据\n", "已获取 9600 条数据\n", "已获取 9700 条数据\n", "已获取 9800 条数据\n", "已获取 9900 条数据\n", "已获取 10000 条数据\n", "已获取 10100 条数据\n", "已获取 10200 条数据\n", "已获取 10300 条数据\n", "已获取 10400 条数据\n", "已获取 10500 条数据\n", "已获取 10600 条数据\n", "已获取 10700 条数据\n", "已获取 10800 条数据\n", "已获取 10900 条数据\n", "已获取 11000 条数据\n", "已获取 11100 条数据\n", "已获取 11200 条数据\n", "已获取 11300 条数据\n", "已获取 11400 条数据\n", "已获取 11500 条数据\n" ] } ], "execution_count": null } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 5 }