diff --git a/.idea/csv-editor.xml b/.idea/csv-editor.xml
index 27fd46a..14f7068 100644
--- a/.idea/csv-editor.xml
+++ b/.idea/csv-editor.xml
@@ -10,6 +10,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 2f2d1c3..0accdec 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -3,76 +3,10 @@
diff --git a/api.py b/api.py
index 6dd4657..fb79b19 100644
--- a/api.py
+++ b/api.py
@@ -3,7 +3,6 @@ API 模块
"""
import requests
-import json
from typing import Optional, List, Dict, Any
from config import Config
from decimal import Decimal
@@ -66,7 +65,6 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
data_get = res.json()
- print(data_get)
if replace:
data_get = self.field_replacement(data, data_get) # 字段替换,由id替换为标签名
@@ -106,25 +104,23 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常
data_get = res.json()
- # print("返回结果:", data_get)
if data_get["data"]:
all_data_batches.extend(data_get['data'])
last_data_id = data_get['data'][-1].get('_id')
- print(f"已获取 {len(all_data_batches)} 条数据")
+ logger.info(f"已获取 {len(all_data_batches)} 条数据")
break # 成功则跳出循环
else:
if 'data' not in data_get or len(data_get['data']) == 0:
exit_flag = True
break
- print("请求失败, 将重新请求")
+ logger.warning(f"请求异常, 将重新请求")
retries += 1
time.sleep(0.1) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(0.1) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(f"任务 {last_data_id}组 连续{max_retries}次请求失败,放弃此次请求。")
all_data_batches.append(None) # 或者可以选择记录失败的payload以便后续处理
@@ -137,7 +133,7 @@ class API:
}
if replace:
print("进行了替换")
- return_data = self.field_replacement(data, final_data)# 字段替换,由id替换为标签名
+ return_data = self.field_replacement(data, final_data) # 字段替换,由id替换为标签名
return return_data
else:
@@ -164,11 +160,8 @@ class API:
})
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
- # print(type(res.json()))
return res.json()
-
-
def field_replacement(self, data: dict, data_get: dict) -> dict:
"""
字段替换,将id替换为标签名,即唯一值替换为表单中显示字段的名字
@@ -245,19 +238,17 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常
data_get = res.json()
- # print("返回结果:", data_get)
if res.status_code == 200:
return data_get
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(
f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。")
@@ -292,11 +283,10 @@ class API:
# 获取data_list长度
total_length = len(data['data_list'])
- print(f"多数据写入行数: {total_length}")
+ logger.info(f"多数据写入行数: {total_length}")
# 计算需要发送的次数
num_chunks = (total_length + chunk_size - 1) // chunk_size # //整除向下取证,需要加上chunk_size - 1保证不会有缺失数据
- print(num_chunks)
data_get_list = []
for i in range(num_chunks):
start_index = i * chunk_size
@@ -314,20 +304,18 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常
data_get = res.json()
- print(i, "返回结果:", data_get)
if data_get["status"] == "success":
data_get_list.append(data_get)
break # 成功则跳出循环
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常,将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(0.1) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(
f"任务 {data['data_list'][start_index:end_index]} 连续{max_retries}次请求失败,放弃此次请求。")
data_get_list.append(None) # 或者可以选择记录失败的payload以便后续处理
@@ -364,19 +352,17 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常
data_get = res.json()
- print("返回结果:", data_get)
if res.status_code == 200:
break # 成功则跳出循环
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(10) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(f"任务 {data['data_id']} 连续{max_retries}次请求失败,放弃此次请求。")
continue
return data_get
@@ -414,25 +400,24 @@ class API:
"code": 4001,
"msg": "Data does not exist."
}:
- print("返回结果:", delete_status)
+ logger.info(f"返回结果:, {delete_status}")
break # 成功则跳出循环
# 检查其他状态码
res.raise_for_status() # 只对非 4001 的状态码进行检查
- print("返回结果:", delete_status)
+ logger.info(f"返回结果:, {delete_status}")
if res.status_code == 200:
break # 成功则跳出循环
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(10) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(f"任务 {data['data_id']} 连续{max_retries}次请求失败,放弃此次请求。")
continue
return delete_status
@@ -461,11 +446,10 @@ class API:
# 获取data_list长度
total_length = len(data['data_ids'])
- print(f"多数据删除行数: {total_length}")
+ logger.info(f"多数据删除行数: {total_length}")
# 计算需要发送的次数
num_chunks = (total_length + chunk_size - 1) // chunk_size # //整除向下取证,需要加上chunk_size - 1保证不会有缺失数据
- print(num_chunks)
data_get_list = []
for i in range(num_chunks):
@@ -483,20 +467,19 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, timeout=10)
res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常
data_get = res.json()
- print(i, "返回结果:", data_get)
+ logger.info(f"{i}页 返回结果: {data_get}")
if data_get["status"] == "success":
data_get_list.append(data_get)
break # 成功则跳出循环
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(0.1) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(
f"任务 {data['data_list'][start_index:end_index]} 连续{max_retries}次请求失败,放弃此次请求。")
data_get_list.append(None) # 或者可以选择记录失败的payload以便后续处理
@@ -534,15 +517,14 @@ class API:
if res.status_code == 200:
break # 成功则跳出循环
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(0.1) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(f"任务 {data['data_id']} 连续{max_retries}次请求失败,放弃此次请求。")
return data_get
@@ -573,7 +555,7 @@ class API:
return res.json()
@staticmethod
- def get_upload_token(data: dict, max_retries: int = 10) -> dict:
+ def get_upload_token(data: dict, max_retries: int = 10) -> dict[str, Any] | None:
"""
获取文件上传凭证
:param data: 应包含应用ID、表单ID、事务ID
@@ -599,24 +581,24 @@ class API:
res_j = res.json()
upload_url = res_j['token_and_url_list'][0]['url']
upload_token = res_j['token_and_url_list'][0]['token']
- print("返回结果:", upload_url, upload_token)
+ logger.info(f"返回结果: {upload_url}, {upload_token}")
if res.status_code == 200:
return {
'upload_url': upload_url,
'upload_token': upload_token
}
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(
f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。")
+ return None
@staticmethod
def upload_file(data: dict, max_retries: int = 10) -> dict:
@@ -645,19 +627,18 @@ class API:
res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10)
res.raise_for_status() # 检查HTTP响应状态码,如果不等于200会抛出异常
data_get = res.json()
- print("返回结果:", data_get)
+ logger.info(f"返回结果: {data_get}")
if res.status_code == 200:
return data_get
else:
- print("请求失败, 将重新请求")
+ logger.warrning(f"请求异常, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
except requests.exceptions.RequestException as e:
- print(f"请求异常: {e}, 将重新请求")
+ logger.warrning(f"请求异常: {e}, 将重新请求")
retries += 1
time.sleep(3) # 在重试之间稍作停顿
if retries > max_retries:
- print(f"超过最大重试次数({max_retries}),放弃此次请求")
error_task_logger.error(
f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。")
diff --git a/back_ground_module/Exception_Task.py b/back_ground_module/Exception_Task.py
index 982703d..664bd37 100644
--- a/back_ground_module/Exception_Task.py
+++ b/back_ground_module/Exception_Task.py
@@ -1,11 +1,8 @@
import datetime
import os
import time
-
import requests
-
from api import API
-import re
from back_ground_module import CommonModule
import pandas as pd
from log_config import configure_task_logger, configure_error_task_logger
@@ -179,152 +176,149 @@ class NewExceptionTask:
def main(self):
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ global png_url, key, upload_key, province_name, city_name, area_name
+ self.load_all_data()
- global png_url, key, upload_key
- self.load_all_data()
+ self.data_yichang_S = common_module.get_yichang_details(days_back=1).astype(str) # 获取data_NGV 并转为str
+ self.index = self.build_index(self.json_list)
- self.data_yichang_S = common_module.get_yichang_details(days_back=1).astype(str) # 获取data_NGV 并转为str
- self.index = self.build_index(self.json_list)
+ logger.info("开始运行SaaS异常回访")
- print("开始运行main")
- print(self.date_one)
+ data_yichang = self.data_yichang_S.copy()
- data_yichang = self.data_yichang_S.copy()
+ def replace_values(series):
+ # 使用条件判断来进行替换
+ return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
- def replace_values(series):
- # 使用条件判断来进行替换
- return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
+ # 对整个DataFrame的所有列应用替换函数
+ data_yichang = data_yichang.apply(replace_values)
- # 对整个DataFrame的所有列应用替换函数
- data_yichang = data_yichang.apply(replace_values)
+ for index_num, row in data_yichang.iterrows(): # 对过滤后的每一条进行派发
+ try:
+ payload_dict = {}
- print(data_yichang.iterrows())
- for index_num, row in data_yichang.iterrows(): # 对过滤后的每一条进行派发
- try:
- print("1111")
- payload_dict = {}
+ distribution_date = datetime.datetime.now(datetime.timezone.utc)
+ distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
- distribution_date = datetime.datetime.now(datetime.timezone.utc)
- distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
+ date_obj1 = datetime.datetime.strptime(row["init_day"], "%Y%m%d").strftime("%Y-%m-%d")
+ date_obj2 = datetime.datetime.strptime(row["push_day"], "%Y%m%d").strftime("%Y-%m-%d")
- date_obj1 = datetime.datetime.strptime(row["init_day"], "%Y%m%d").strftime("%Y-%m-%d")
- date_obj2 = datetime.datetime.strptime(row["push_day"], "%Y%m%d").strftime("%Y-%m-%d")
+ NGV_roles = {
+ 'service_impl_principal': row['service_impl_principal'], # 运营负责人
+ 'area_manager': row['area_manager'], # 区域经理
+ 'technician': row['technician'], # 运营专家
+ }
+ for role, name in NGV_roles.items(): # 寻找对应的员工ID
+ for row_item in self.staff_id_list:
+ staff_id = self.get_staff_id(row_item, name)
+ if staff_id:
+ NGV_roles[role] = staff_id
+ break # 找到后退出循环
+ else:
+ NGV_roles[role] = None # 如果没有找到对应的员工ID
+ relationship_manager, area_manager, technician = [NGV_roles[role] for role in
+ ['service_impl_principal',
+ 'area_manager',
+ 'technician']]
- NGV_roles = {
- 'service_impl_principal': row['service_impl_principal'], # 运营负责人
- 'area_manager': row['area_manager'], # 区域经理
- 'technician': row['technician'], # 运营专家
- }
- print('NGV_roles', NGV_roles)
- for role, name in NGV_roles.items(): # 寻找对应的员工ID
- for row_item in self.staff_id_list:
- staff_id = self.get_staff_id(row_item, name)
- if staff_id:
- NGV_roles[role] = staff_id
- break # 找到后退出循环
- else:
- NGV_roles[role] = None # 如果没有找到对应的员工ID
- print('NGV_roles[role]', NGV_roles)
- relationship_manager, area_manager, technician = [NGV_roles[role] for role in
- ['service_impl_principal',
- 'area_manager',
- 'technician']]
+ UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
- UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
+ NGV_data_id = None
+ # 获取关联数据
+ for NGV_Data in self.NGV_data_list:
+ # NGV_Data = NGV_Data.get("data")
+ if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
+ NGV_data_id = NGV_Data.get("_id")
+ province_name = NGV_Data.get("_widget_1734062123090")
+ city_name = NGV_Data.get("_widget_1734062123092")
+ area_name = NGV_Data.get("_widget_1734062123094")
+ logger.info(f"获取关联数据成功:{NGV_data_id}, {province_name}, {city_name}, {area_name}")
- NGV_data_id = None
- # 获取关联数据
- for NGV_Data in self.NGV_data_list:
- # NGV_Data = NGV_Data.get("data")
- if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
- NGV_data_id = NGV_Data.get("_id")
- province_name = NGV_Data.get("_widget_1734062123090")
- city_name = NGV_Data.get("_widget_1734062123092")
- area_name = NGV_Data.get("_widget_1734062123094")
- print('111111', NGV_data_id, province_name, city_name, area_name)
+ if not NGV_data_id:
+ logger.warning(f"未找到关联数据,请检查门店编码: {row['org_code']}")
- if not NGV_data_id:
- print("未找到数据ID")
+ # 根据省市区派发给异常回访客服
+ customer_service = self.assign_customer_service(province_name, city_name, area_name, self.index)
- # 根据省市区派发给异常回访客服
- print('333', province_name, city_name, area_name)
- customer_service = self.assign_customer_service(province_name, city_name, area_name, self.index)
+ payload_dict.update({
+ "_widget_1748241895829": {"value": row["health_warning_info"]}, # 活跃健康状态变化
- payload_dict.update({
- "_widget_1748241895829": {"value": row["health_warning_info"]}, # 活跃健康状态变化
+ "_widget_1748241895830": {"value": row["org_name"]}, # 门店名称
- "_widget_1748241895830": {"value": row["org_name"]}, # 门店名称
+ "_widget_1748241895831": {"value": row["contacts"]}, # 联系人
- "_widget_1748241895831": {"value": row["contacts"]}, # 联系人
+ "_widget_1748241895832": {"value": row['contact_mobile']}, # 联系方式
- "_widget_1748241895832": {"value": row['contact_mobile']}, # 联系方式
+ "_widget_1748241895833": {
+ "value": int(time.mktime(time.strptime(date_obj1, "%Y-%m-%d")) * 1000) if row[
+ "init_day"] != '' else ''},
+ # 初始日
- "_widget_1748241895833": {"value": int(time.mktime(time.strptime(date_obj1, "%Y-%m-%d")) * 1000) if row[
- "init_day"] != '' else ''},
- # 初始日
+ "_widget_1748241895834": {
+ "value": int(time.mktime(time.strptime(date_obj2, "%Y-%m-%d")) * 1000) if row[
+ "push_day"] != '' else ''},
+ # 推进日
- "_widget_1748241895834": {"value": int(time.mktime(time.strptime(date_obj2, "%Y-%m-%d")) * 1000) if row[
- "push_day"] != '' else ''},
- # 推进日
+ "_widget_1748246808678": {"value": customer_service}, # 当前跟进人
- "_widget_1748246808678": {"value": customer_service}, # 当前跟进人
+ "_widget_1748246808679": {"value": relationship_manager}, # 运营负责人
- "_widget_1748246808679": {"value": relationship_manager}, # 运营负责人
+ "_widget_1748246808680": {"value": customer_service}, # 区域客服
- "_widget_1748246808680": {"value": customer_service}, # 区域客服
+ "_widget_1748241895839": {
+ "value": int(time.mktime(time.strptime(row["saas_create_time"], "%Y-%m-%d")) * 1000) if row[
+ "saas_create_time"] != '' else ''},
+ # 开户时间
- "_widget_1748241895839": {
- "value": int(time.mktime(time.strptime(row["saas_create_time"], "%Y-%m-%d")) * 1000) if row[
- "saas_create_time"] != '' else ''},
- # 开户时间
+ "_widget_1748246808681": {"value": technician}, # 技术专家
- "_widget_1748246808681": {"value": technician}, # 技术专家
+ "_widget_1748246808682": {"value": area_manager}, # 区域经理
- "_widget_1748246808682": {"value": area_manager}, # 区域经理
+ "_widget_1748241895842": {"value": row['org_code']}, # 门店编码
- "_widget_1748241895842": {"value": row['org_code']}, # 门店编码
+ "_widget_1748241895844": {"value": row['group_name']}, # 公司名称
- "_widget_1748241895844": {"value": row['group_name']}, # 公司名称
+ "_widget_1748241895846": {"value": row['group_grade']}, # 公司等级
- "_widget_1748241895846": {"value": row['group_grade']}, # 公司等级
+ "_widget_1748241895847": {"value": row['region_name']}, # 大区
- "_widget_1748241895847": {"value": row['region_name']}, # 大区
+ "_widget_1748241895848": {"value": row['province_name']}, # 省
- "_widget_1748241895848": {"value": row['province_name']}, # 省
+ "_widget_1748241895849": {"value": row['org_type']}, # 门店类型
- "_widget_1748241895849": {"value": row['org_type']}, # 门店类型
+ "_widget_1748241895850": {"value": row['saas_edition_fmt']}, # 系统版本
- "_widget_1748241895850": {"value": row['saas_edition_fmt']}, # 系统版本
+ "_widget_1748241895851": {"value": row['saas_customer_type']}, # saas客户类型
- "_widget_1748241895851": {"value": row['saas_customer_type']}, # saas客户类型
+ "_widget_1748241895852": {"value": row['org_stage']}, # 门店阶段
- "_widget_1748241895852": {"value": row['org_stage']}, # 门店阶段
+ "_widget_1748241895853": {"value": row['contact_mobile']}, # 操作模式E.L/E.S
- "_widget_1748241895853": {"value": row['contact_mobile']}, # 操作模式E.L/E.S
+ "_widget_1748241895855": {"value": row['city_name']}, # 城市
- "_widget_1748241895855": {"value": row['city_name']}, # 城市
+ "_widget_1748247754304": {"value": NGV_data_id}, # 数据id
- "_widget_1748247754304": {"value": NGV_data_id}, # 数据id
+ "_widget_1748512176655": {"value": "未处理"}, # 跟进状态
- "_widget_1748512176655": {"value": "未处理"}, # 跟进状态
+ })
- })
+ routine_follow_up_payload = {
+ "api_key": "675b900991ad2491c69389ca",
+ "entry_id": "68340de79f116c0b66b6b0cc", # 异常服务跟进待办
+ "is_start_workflow": "true",
+ "data": payload_dict,
+ "transaction_id": UUid
+ }
- routine_follow_up_payload = {
- "api_key": "675b900991ad2491c69389ca",
- "entry_id": "68340de79f116c0b66b6b0cc", # 异常服务跟进待办
- "is_start_workflow": "true",
- "data": payload_dict,
- "transaction_id": UUid
- }
-
- # print(routine_follow_up_payload)
-
- res = api_instance.data_batch_create(routine_follow_up_payload)
- logger.info(f"创建结果:{res}")
- except:
- pass
- common_module.send_task_status(task_start_time, "异常服务待办派发")
+ res = api_instance.data_batch_create(routine_follow_up_payload)
+ logger.info(f"创建结果:{res}")
+ except:
+ pass
+ common_module.send_task_status(task_start_time, "异常服务待办派发")
+ except Exception as e:
+ error_task_logger.error(f"异常服务待办派发执行时发生异常: {e}")
+ common_module.send_task_error(task_start_time, "异常服务待办派发", str(e))
if __name__ == '__main__':
diff --git a/back_ground_module/JCB_abnormal_revisit.py b/back_ground_module/JCB_abnormal_revisit.py
index 15a9e4a..07f55cf 100644
--- a/back_ground_module/JCB_abnormal_revisit.py
+++ b/back_ground_module/JCB_abnormal_revisit.py
@@ -1,18 +1,29 @@
-from datetime import date, timedelta, datetime
-import holidays
+from datetime import timedelta, datetime
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
+from log_config import configure_task_logger, configure_error_task_logger
+
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+# 获取已经配置好的错误任务日志记录器
+error_task_logger = configure_error_task_logger()
common_module = CommonModule()
api_instance = API()
+# 保存为CSV文件
+output_dir = "output" # 设置输出目录
+
+# 创建输出目录(如果不存在)
+import os
+
+os.makedirs(output_dir, exist_ok=True)
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
@@ -47,6 +58,7 @@ class JCBAbnormalRevisit:
def today_customer_service_list(self):
# 获取今日接车宝派发客服顺序
+ global is_customer_service_data_id
today_customer_service_list = []
all_customer_service_list = []
today_customer_service_start_list = []
@@ -112,7 +124,7 @@ class JCBAbnormalRevisit:
df.iterrows()]
data = {'api_key': Config.EFFICIENT_CAR_PICKUP_APP_ID, 'entry_id': "67174710da507490d8ac12c1",
- "data_list": new_sign_abnormal_data} # 派发数据
+ "data_list": new_sign_abnormal_data} # 派发数据
api_instance.entry_data_batch_create(data)
@@ -133,197 +145,190 @@ class JCBAbnormalRevisit:
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
"data_id": next_customer_service_data_id,
"data":
- {"_widget_1740042824216": {"value": "是"}, }}# 明日派发起点人员
+ {"_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")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ logger.info(f"开始执行")
+ self.load_all_data()
+ data_JCB = common_module.get_jcb_details()
+ logger.info(f"数据加载完成")
+ # data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
+ self.fields()
- data_JCB = common_module.get_jcb_details()
+ # 异常待办回访 近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(所有异常待办)
- # 保存为CSV文件
- output_dir = "output" # 设置输出目录
+ 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])
- # 创建输出目录(如果不存在)
- import os
- os.makedirs(output_dir, exist_ok=True)
+ 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
- # data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
- self.fields()
+ # 将 '联系手机号' 列转换为字符串类型
+ 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
- # 异常待办回访 近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(所有异常待办)
+ today = datetime.now().weekday()
- 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])
+ # 随机抽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存在 ,今日派发与历史派发都存在,派发并删历史
- 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
+ df_40 = df3[df3.index < 40]
+ # df_40.to_excel(os.path.join(output_dir, 'JCB_异常待办情况2.xlsx'), index=False, )
- # 将 '联系手机号' 列转换为字符串类型
- 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
+ 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)
+ logger.info(f"已删除随机抽取40条数据")
- 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'))
+ # 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 的重复列)
- 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(): # 删除已推送的数据
+ 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)
+ logger.info("已删除派发后数据")
- # 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)
- # 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)
- # 合并两个当日派发的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 手动结束
- 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])
- 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)
- 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 = 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['提交时间'] = 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)
- filtered_data_with_latest = pd.merge(
- filtered_data,
- latest_update_time,
- left_on=['账号', '提交时间'],
- right_on=['账号', '最新提交时间']
- )
+ latest_JDY_abnormal_data['提交时间'] = pd.to_datetime(latest_JDY_abnormal_data['提交时间']).dt.strftime(
+ "%Y-%m-%d")
- # 过滤出每个账号中提交时间为最新的记录
- 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)
+ 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天的数据
- latest_JDY_abnormal_data['提交时间'] = pd.to_datetime(latest_JDY_abnormal_data['提交时间']).dt.strftime("%Y-%m-%d")
+ # final_JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_最新数据.xlsx'), index=False)
- thirty_days_ago = (current_date - timedelta(days=30)).strftime("%Y-%m-%d")
+ 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)
- final_JDY_abnormal_data = latest_JDY_abnormal_data[latest_JDY_abnormal_data['提交时间'] > thirty_days_ago] # 筛选出提交时间为近30天的数据
+ self.send_request(df_abnormal_data)
+ common_module.send_task_status(task_start_time, "接车宝异常派发")
+ logger.info("接车宝异常派发完成")
- # 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)
+ except Exception as e:
+ common_module.send_task_error(task_start_time, "接车宝异常派发", str(e))
+ error_task_logger.error(f"接车宝异常派发执行异常: {e}")
@staticmethod
def row_to_dict(row, field_mapping):
diff --git a/back_ground_module/JCB_efficient_car_pickup.py b/back_ground_module/JCB_efficient_car_pickup.py
index 9314f2b..da33bbb 100644
--- a/back_ground_module/JCB_efficient_car_pickup.py
+++ b/back_ground_module/JCB_efficient_car_pickup.py
@@ -1,18 +1,27 @@
-from datetime import date, timedelta, datetime
-import holidays
+from datetime import timedelta, datetime
from config import Config
import pandas as pd
-import pymysql # 使用 pymysql 替代 mysql.connector
from back_ground_module import CommonModule
-from log_config import configure_task_logger, configure_error_task_logger
from api import API
+from log_config import configure_task_logger, configure_error_task_logger
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+# 获取已经配置好的错误任务日志记录器
+error_task_logger = configure_error_task_logger()
+# 保存为CSV文件
+output_dir = "output" # 设置输出目录
+# 创建输出目录(如果不存在)
+import os
+
+os.makedirs(output_dir, exist_ok=True)
common_module = CommonModule()
api_instance = API()
class JCBEfficientCarPickup:
"""接车宝日常回访"""
+
def __init__(self):
# 使用 pymysql 连接数据库
self.field_mapping = {}
@@ -30,6 +39,7 @@ class JCBEfficientCarPickup:
def today_customer_service_list(self):
# 获取今日接车宝派发客服顺序
+ global is_customer_service_data_id
today_customer_service_list = []
all_customer_service_list = []
today_customer_service_start_list = []
@@ -98,6 +108,7 @@ class JCBEfficientCarPickup:
"data_list": new_sign_abnormal_data}
result = api_instance.entry_data_batch_create(data)
+ logger.info(f"数据发送成功:{result}")
data1 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
@@ -119,108 +130,111 @@ class JCBEfficientCarPickup:
{"_widget_1740042824216": {"value": "是"}, }}
api_instance.entry_data_update(data1)
- api_instance.entry_data_update(data2)
+ result2 = api_instance.entry_data_update(data2)
+ logger.info(f"明日派发人员信息已修改:{result2}")
def main(self):
- task_start_time =datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ logger.info(f"接车宝日常回访开始执行")
+ data_JCB = common_module.get_jcb_details()
+ logger.info(f"数据加载完成")
- data_JCB = common_module.get_jcb_details()
- print(data_JCB)
+ # data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
+ self.fields()
- # 保存为CSV文件
- output_dir = "output" # 设置输出目录
+ # 新签异常待办回访。
+ # 当前日期
+ current_date = datetime.now()
+ current_date = current_date + timedelta(days=0)
+ current_date_str = current_date.strftime("%Y-%m-%d")
- # 创建输出目录(如果不存在)
- import os
- os.makedirs(output_dir, exist_ok=True)
+ seven_days_ago = current_date - timedelta(days=7)
+ seven_days_ago = seven_days_ago.date()
+ # print(three_days_ago)
+ new_sign_abnormal = []
- # data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
- self.fields()
+ for index, row in data_JCB.iterrows():
+ new_row = row.copy()
+ # 先转成字符串,再解析回 date 对象
+ new_row['开户日'] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
+ if new_row['开户日'] == seven_days_ago and row['当月开单天数'] == 0:
+ # print(row['账号'], row['开户日'], row['当月开单天数'])
+ row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
+ row['日期'] = row["日期"].strftime("%Y-%m-%d")
+ new_sign_abnormal.append(row)
- # 新签异常待办回访。
- # 当前日期
- current_date = datetime.now()
- current_date = current_date + timedelta(days=0)
- current_date_str = current_date.strftime("%Y-%m-%d")
+ new_sign_abnormal = pd.DataFrame(new_sign_abnormal)
+ new_sign_abnormal["表单类型"] = "新签异常待办"
+ new_sign_abnormal["派发日期"] = current_date_str
- seven_days_ago = current_date - timedelta(days=7)
- seven_days_ago = seven_days_ago.date()
- # print(three_days_ago)
- new_sign_abnormal = []
+ self.send_request(new_sign_abnormal) # 发送请求
+ logger.info(f"新签异常待办回访完成")
- for index, row in data_JCB.iterrows():
- new_row = row.copy()
- # 先转成字符串,再解析回 date 对象
- new_row['开户日'] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
- if new_row['开户日'] == seven_days_ago and row['当月开单天数'] == 0:
- # print(row['账号'], row['开户日'], row['当月开单天数'])
- row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
- row['日期'] = row["日期"].strftime("%Y-%m-%d")
- new_sign_abnormal.append(row)
+ # 优质客户转商机
+ # current_date = datetime.now()
+ thirty_days_ago = current_date - timedelta(days=30)
+ sixty_days_ago = current_date - timedelta(days=60)
+ thirty_days_ago = thirty_days_ago.date()
+ sixty_days_ago = sixty_days_ago.date()
+ customer_to_opportunity = []
+ for index, row in data_JCB.iterrows():
+ new_row = row.copy()
+ # 先转成字符串,再解析回 date 对象
+ new_row['到期日'] = datetime.strptime(str(row['到期日']), "%Y-%m-%d").date()
+ if new_row['到期日'] == thirty_days_ago and row['近一周开单量'] >= 3 and row[
+ 'G状态:近30天开单大于等于10天'] == 1:
+ print(row['账号'], row['到期日'], row['当月开单天数'], row['当月G天数'])
+ row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
+ row['日期'] = row["日期"].strftime("%Y-%m-%d")
+ customer_to_opportunity.append(row)
+ # 推送给客服
+ pass
+ if new_row['到期日'] == sixty_days_ago and row['近一周开单量'] >= 3 and row[
+ 'G状态:近30天开单大于等于10天'] == 1:
+ print(row['账号'], row['到期日'], row['当月开单天数'], row['当月G天数'])
+ row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
+ row['日期'] = row["日期"].strftime("%Y-%m-%d")
+ customer_to_opportunity.append(row)
+ # 推送给客服
+ pass
- new_sign_abnormal = pd.DataFrame(new_sign_abnormal)
- new_sign_abnormal["表单类型"] = "新签异常待办"
- new_sign_abnormal["派发日期"] = current_date_str
+ customer_to_opportunity = pd.DataFrame(customer_to_opportunity)
+ customer_to_opportunity["表单类型"] = "续约优质客户转商机"
+ customer_to_opportunity["派发日期"] = current_date_str
- self.send_request(new_sign_abnormal) # 发送请求
+ self.send_request(customer_to_opportunity)
+ logger.info(f"优质客户转商机完成")
- # 优质客户转商机
- # current_date = datetime.now()
- thirty_days_ago = current_date - timedelta(days=30)
- sixty_days_ago = current_date - timedelta(days=60)
- thirty_days_ago = thirty_days_ago.date()
- sixty_days_ago = sixty_days_ago.date()
- customer_to_opportunity = []
- for index, row in data_JCB.iterrows():
- new_row = row.copy()
- # 先转成字符串,再解析回 date 对象
- new_row['到期日'] = datetime.strptime(str(row['到期日']), "%Y-%m-%d").date()
- if new_row['到期日'] == thirty_days_ago and row['近一周开单量'] >= 3 and row[
- 'G状态:近30天开单大于等于10天'] == 1:
- print(row['账号'], row['到期日'], row['当月开单天数'], row['当月G天数'])
- row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
- row['日期'] = row["日期"].strftime("%Y-%m-%d")
- customer_to_opportunity.append(row)
- # 推送给客服
- pass
- if new_row['到期日'] == sixty_days_ago and row['近一周开单量'] >= 3 and row[
- 'G状态:近30天开单大于等于10天'] == 1:
- print(row['账号'], row['到期日'], row['当月开单天数'], row['当月G天数'])
- row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
- row['日期'] = row["日期"].strftime("%Y-%m-%d")
- customer_to_opportunity.append(row)
- # 推送给客服
- pass
+ # 过期7天客服回访
+ # current_date = datetime.now()
+ seven_days_ago = current_date - timedelta(days=7)
+ seven_days_ago = seven_days_ago.date()
+ outdated_30 = []
+ for index, row in data_JCB.iterrows():
+ new_row = row.copy()
+ new_row['到期日'] = datetime.strptime(str(row['到期日']), "%Y-%m-%d").date()
+ # seven_days_ago = seven_days_ago.date()
+ # print(row['到期日'], seven_days_ago)
+ if new_row['到期日'] == seven_days_ago and row['客户状态'] == "过期":
+ print(row['账号'], row['到期日'], row['当月开单天数'], row['当月G天数'])
+ row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
+ row['日期'] = row["日期"].strftime("%Y-%m-%d")
+ outdated_30.append(row)
+ # 推送给客服
+ pass
- customer_to_opportunity = pd.DataFrame(customer_to_opportunity)
- customer_to_opportunity["表单类型"] = "续约优质客户转商机"
- customer_to_opportunity["派发日期"] = current_date_str
+ outdated_30 = pd.DataFrame(outdated_30)
+ outdated_30["表单类型"] = "过期7天回访"
+ outdated_30["派发日期"] = current_date_str
+ self.send_request(outdated_30)
+ logger.info(f"过期7天客服回访完成")
- self.send_request(customer_to_opportunity)
-
- # 过期7天客服回访
- # current_date = datetime.now()
- seven_days_ago = current_date - timedelta(days=7)
- seven_days_ago = seven_days_ago.date()
- outdated_30 = []
- for index, row in data_JCB.iterrows():
- new_row = row.copy()
- new_row['到期日'] = datetime.strptime(str(row['到期日']), "%Y-%m-%d").date()
- # seven_days_ago = seven_days_ago.date()
- # print(row['到期日'], seven_days_ago)
- if new_row['到期日'] == seven_days_ago and row['客户状态'] == "过期":
- print(row['账号'], row['到期日'], row['当月开单天数'], row['当月G天数'])
- row["日期"] = datetime.strptime(str(row['开户日']), "%Y-%m-%d").date()
- row['日期'] = row["日期"].strftime("%Y-%m-%d")
- outdated_30.append(row)
- # 推送给客服
- pass
-
- outdated_30 = pd.DataFrame(outdated_30)
- outdated_30["表单类型"] = "过期7天回访"
- outdated_30["派发日期"] = current_date_str
- self.send_request(outdated_30)
- common_module.send_task_status(task_start_time, "接车宝日常派发")
+ common_module.send_task_status(task_start_time, "接车宝日常派发")
+ logger.info(f"接车宝日常派发执行完成")
+ except Exception as e:
+ common_module.send_task_error(task_start_time, "接车宝日常派发", str(e))
+ error_task_logger.error(f"接车宝日常派发执行出错:{e}")
@staticmethod
def row_to_dict(row, field_mapping):
diff --git a/back_ground_module/common_module.py b/back_ground_module/common_module.py
index 3516181..84b793b 100644
--- a/back_ground_module/common_module.py
+++ b/back_ground_module/common_module.py
@@ -249,7 +249,7 @@ class CommonModule:
]
data_NGV.columns = headers
- cols_to_str =["日期","开户日","续约日","到期日"]
+ cols_to_str = ["日期", "开户日", "续约日", "到期日"]
data_NGV[cols_to_str] = data_NGV[cols_to_str].apply(lambda x: x.astype(str))
data_NGV.to_csv(os.path.join(output_dir, f"{target_date_id}.csv"), index=False)
@@ -576,7 +576,6 @@ class CommonModule:
:param task_start_time: 任务开始时间(字符串格式:"%Y-%m-%d %H:%M:%S",表示北京时间 UTC+8)
:param task_name: 任务名称
"""
- print(1)
try:
# 1. 获取当前 UTC 时间(时区感知对象)
end_time_utc = datetime.now(UTC) # ✅ 替代 utcnow()
@@ -596,8 +595,6 @@ class CommonModule:
today_utc = end_time_utc.strftime("%Y-%m-%d")
task_end_iso = end_time_utc.strftime("%Y-%m-%dT%H:%M:%SZ")
task_start_iso = task_start_utc.strftime("%Y-%m-%dT%H:%M:%SZ")
- print(task_end_iso)
- print(task_start_iso)
# 6. 构造请求数据(所有时间以 UTC 格式发送)
payload = {
@@ -617,4 +614,54 @@ class CommonModule:
logger.info(f"任务状态发送成功: {response}")
except Exception as e:
- logger.error(f"任务状态发送失败: {e}")
+ error_task_logger.error(f"任务状态发送失败: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ CommonModule.send_task_error(task_start_time, "发送任务状态", e)
+
+ def send_task_error(self, task_start_time: str, task_name: str, error_message: str) -> None:
+ """
+ 将任务失败情况发送到简道云(影响业务数据时调用)
+ :param task_start_time: 任务开始时间(字符串格式:"%Y-%m-%d %H:%M:%S",表示北京时间 UTC+8)
+ :param task_name: 任务名称
+ :param error_message: 失败详情
+ """
+ try:
+ # 1. 获取当前 UTC 时间(时区感知对象)
+ end_time_utc = datetime.now(UTC) # ✅ 替代 utcnow()
+
+ # 2. 解析传入的北京时间(UTC+8)
+ task_start_naive = datetime.strptime(task_start_time, "%Y-%m-%d %H:%M:%S")
+
+ # 3. 转换为 UTC 时间(减去 8 小时,并附加 UTC 时区)
+ task_start_utc = task_start_naive - timedelta(hours=8)
+ task_start_utc = task_start_utc.replace(tzinfo=timezone.utc) # 显式标记为 UTC
+
+ # 4. 计算运行时间(时区感知对象可直接相减)
+ run_time = end_time_utc - task_start_utc
+ run_time_sec = int(run_time.total_seconds())
+
+ # 5. 格式化时间为 UTC 的 ISO 8601 格式(带 "Z")
+ today_utc = end_time_utc.strftime("%Y-%m-%d")
+ task_end_iso = end_time_utc.strftime("%Y-%m-%dT%H:%M:%SZ")
+ task_start_iso = task_start_utc.strftime("%Y-%m-%dT%H:%M:%SZ")
+
+ # 6. 构造请求数据(所有时间以 UTC 格式发送)
+ payload = {
+ "api_key": Config.SCHEDULED_TASKS_APP_ID,
+ "entry_id": Config.JDY_TASKS_ERROR_ENTRY_ID,
+ "data": {
+ "_widget_1744873387500": {"value": today_utc}, # UTC 日期
+ "_widget_1743644977694": {"value": task_name},
+ "_widget_1744873387501": {"value": task_start_iso}, # UTC 开始时间
+ "_widget_1744873387502": {"value": task_end_iso}, # UTC 结束时间
+ "_widget_1744873387504": {"value": run_time_sec},
+ "_widget_1754981992215": {"value": error_message}, # 错误信息
+ }
+ }
+
+ # 7. 发送请求
+ response = api_instance.data_batch_create(payload)
+ logger.info(f"任务错误发生成功: {response}")
+
+ except Exception as e:
+ error_task_logger.error(f"任务错误发送失败: {e}")
diff --git a/back_ground_module/data_Support_Commission.py b/back_ground_module/data_Support_Commission.py
index c916287..6229ebb 100644
--- a/back_ground_module/data_Support_Commission.py
+++ b/back_ground_module/data_Support_Commission.py
@@ -4,8 +4,15 @@ import datetime
from config import Config
from api import API
import pymysql # 使用 pymysql 替代 mysql.connector
+from log_config import configure_task_logger, configure_error_task_logger
from back_ground_module import CommonModule
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+
+# 获取已经配置好的错误任务日志记录器
+error_task_logger = configure_error_task_logger()
+
start_time = datetime.datetime.now()
api_instance = API()
common_module = CommonModule()
@@ -15,47 +22,43 @@ class importCommissionData:
"""
小六提成数据支撑
"""
+
def __init__(self):
self.field_mapping = {}
self.fields()
def main(self):
- task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- payload = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.Commission_form_ID,
- }
- abnormal_service = api_instance.entry_data_list(payload)
- abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
- for i in range(0,len(abnormal_list)): # 删除历史数据
+ task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.Commission_form_ID,
+ }
+ abnormal_service = api_instance.entry_data_list(payload)
+ abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
+ delete_id_list = []
try:
- delete_data = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.Commission_form_ID,
- "data_id": abnormal_list[i]['_id']}
- api_instance.entry_data_delete(delete_data)
- except:
- pass
+ for i in range(0, len(abnormal_list)): # 删除历史数据
+ delete_id_list.append(abnormal_list[i]['_id'])
+ delete_payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.Commission_form_ID,
+ "data_id": delete_id_list}
+ api_instance.entry_data_batch_delete(delete_payload)
- data_commission = common_module.get_commission_details()
+ data_commission = common_module.get_commission_details()
+ except Exception as e:
+ error_task_logger.error(f"小六提成数据支撑任务执行出错:{str(e)}")
+ common_module.send_task_error(task_start_time, "小六提成数据支撑", str(e))
- # 生成包含所有行转换后的字典列表
- data_commission = [self.row_to_dict(row, self.field_mapping) for index, row in data_commission.iterrows()]
- data_commission = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.Commission_form_ID, "data_list": data_commission}
-
- result = api_instance.entry_data_batch_create(data_commission)
- result_str = str(result)
- # print(result_str[:500])
+ # 生成包含所有行转换后的字典列表
+ data_commission = [self.row_to_dict(row, self.field_mapping) for index, row in data_commission.iterrows()]
+ data_commission = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.Commission_form_ID,
+ "data_list": data_commission}
- # 保存到Excel文件
- # output_path = r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细1.xlsx'
- # data_NGV_j.to_excel(output_path, index=False)
-
- end_time = datetime.datetime.now()
-
- time_diff = end_time - start_time
-
- # 打印天数、秒数和微秒数
- print(f"执行时间: {time_diff.days} 天, {time_diff.seconds} 秒, {time_diff.microseconds} 微秒")
- common_module.send_task_status(task_start_time, "小六提成数据支撑")
+ api_instance.entry_data_batch_create(data_commission)
+ common_module.send_task_status(task_start_time, "小六提成数据支撑")
+ except Exception as e:
+ error_task_logger.error(f"小六提成数据支撑任务执行出错:{str(e)}")
+ common_module.send_task_error(task_start_time, "小六提成数据支撑", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
@@ -70,14 +73,16 @@ class importCommissionData:
def fields(self):
self.field_mapping = {
- "门店id": "_widget_1742884710674",
- "提成类型_二级分类": "_widget_1742884710675",
- "提成基数(本月)": "_widget_1742884710676",
- "提成基数(上月)": "_widget_1742884710677",
- "公司id": "_widget_1748930441629",
- "门店编码": "_widget_1748931089356",
- "门店名称": "_widget_1748931089357"
- }
+ "门店id": "_widget_1742884710674",
+ "提成类型_二级分类": "_widget_1742884710675",
+ "提成基数(本月)": "_widget_1742884710676",
+ "提成基数(上月)": "_widget_1742884710677",
+ "公司id": "_widget_1748930441629",
+ "门店编码": "_widget_1748931089356",
+ "门店名称": "_widget_1748931089357"
+ }
+
+
if __name__ == '__main__':
start = importCommissionData()
start.main()
diff --git a/back_ground_module/data_Support_DifferentIndustries.py b/back_ground_module/data_Support_DifferentIndustries.py
index 77130f7..a35f4fd 100644
--- a/back_ground_module/data_Support_DifferentIndustries.py
+++ b/back_ground_module/data_Support_DifferentIndustries.py
@@ -5,6 +5,11 @@ from config import Config
from api import API
import pymysql # 使用 pymysql 替代 mysql.connector
from back_ground_module import CommonModule
+from log_config import configure_task_logger, configure_error_task_logger
+
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
start_time = datetime.datetime.now()
api_instance = API()
@@ -13,48 +18,45 @@ common_module = CommonModule()
class importDifferentIndustriesData:
"""异业合作数据支撑"""
+
def __init__(self):
self.field_mapping = {}
self.fields()
def main(self):
- task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- payload = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.DifferentIndustries_form_ID,
- }
- abnormal_service = api_instance.entry_data_list(payload)
- abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
- for i in range(0,len(abnormal_list)): # 删除历史数据
+ task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.DifferentIndustries_form_ID,
+ }
+ abnormal_service = api_instance.entry_data_list(payload)
+ abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
+
+ delete_id_list = []
try:
- delete_data = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.DifferentIndustries_form_ID,
- "data_id": abnormal_list[i]['_id']}
- api_instance.entry_data_delete(delete_data)
- except:
- pass
+ for i in range(0, len(abnormal_list)): # 删除历史数据
+ delete_id_list.append(abnormal_list[i]['_id'])
+ delete_payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.DifferentIndustries_form_ID,
+ "data_id": delete_id_list}
+ api_instance.entry_data_batch_delete(delete_payload)
+ except Exception as e:
+ error_task_logger.error(f"异业合作数据支撑任务执行时发生异常: {e}")
+ common_module.send_task_error(task_start_time, "异业合作数据支撑", str(e))
+ data_commission = common_module.get_differentindustries_details()
- data_commission = common_module.get_differentindustries_details()
+ # 生成包含所有行转换后的字典列表
+ data_commission = [self.row_to_dict(row, self.field_mapping) for index, row in data_commission.iterrows()]
+ data_commission = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.DifferentIndustries_form_ID,
+ "data_list": data_commission}
- # 生成包含所有行转换后的字典列表
- data_commission = [self.row_to_dict(row, self.field_mapping) for index, row in data_commission.iterrows()]
- data_commission = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.DifferentIndustries_form_ID, "data_list": data_commission}
-
- result = api_instance.entry_data_batch_create(data_commission)
- result_str = str(result)
- # print(result_str[:500])
+ api_instance.entry_data_batch_create(data_commission)
- # 保存到Excel文件
- # output_path = r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细1.xlsx'
- # data_NGV_j.to_excel(output_path, index=False)
-
- end_time = datetime.datetime.now()
-
- time_diff = end_time - start_time
-
- # 打印天数、秒数和微秒数
- print(f"执行时间: {time_diff.days} 天, {time_diff.seconds} 秒, {time_diff.microseconds} 微秒")
- common_module.send_task_status(task_start_time, "异业合作数据支撑")
+ common_module.send_task_status(task_start_time, "异业合作数据支撑")
+ except Exception as e:
+ error_task_logger.error(f"异业合作数据支撑任务执行时发生异常: {e}")
+ common_module.send_task_error(task_start_time, "异业合作数据支撑", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
@@ -69,13 +71,15 @@ class importDifferentIndustriesData:
def fields(self):
self.field_mapping = {
- "门店id": "_widget_1742884829007",
- "商品名称": "_widget_1742884829008",
- "服务期结束时间": "_widget_1742884829009",
- "门店名称": "_widget_1748931208851",
- "公司id": "_widget_1748930826642",
- "门店编码": "_widget_1748931208852"
- }
+ "门店id": "_widget_1742884829007",
+ "商品名称": "_widget_1742884829008",
+ "服务期结束时间": "_widget_1742884829009",
+ "门店名称": "_widget_1748931208851",
+ "公司id": "_widget_1748930826642",
+ "门店编码": "_widget_1748931208852"
+ }
+
+
if __name__ == '__main__':
start = importDifferentIndustriesData()
start.main()
diff --git a/back_ground_module/data_Support_GroupNotification.py b/back_ground_module/data_Support_GroupNotification.py
index d975e3b..8d278bc 100644
--- a/back_ground_module/data_Support_GroupNotification.py
+++ b/back_ground_module/data_Support_GroupNotification.py
@@ -5,7 +5,11 @@ from config import Config
from api import API
import pymysql # 使用 pymysql 替代 mysql.connector
from back_ground_module import CommonModule
+from log_config import configure_task_logger, configure_error_task_logger
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
start_time = datetime.datetime.now()
api_instance = API()
common_module = CommonModule()
@@ -13,59 +17,45 @@ common_module = CommonModule()
class importGroupNotificationData:
"""短信数据支撑"""
+
def __init__(self):
self.field_mapping = {}
self.fields()
def main(self):
- task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- payload = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.GroupNotification_form_ID,
- }
- abnormal_service = api_instance.entry_data_list(payload)
- abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
- # print(abnormal_list)
- delete_id_list = []
- for i in range(0,len(abnormal_list)): # 删除历史数据
+ task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.GroupNotification_form_ID,
+ }
+ abnormal_service = api_instance.entry_data_list(payload)
+ abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
+ delete_id_list = []
try:
- # delete_data = {"api_key": Config.SaaS_Tasks_APP_ID,
- # "entry_id": Config.GroupNotification_form_ID,
- # "data_id": abnormal_list[i]['_id']}
- # api_instance.entry_data_delete(delete_data)
- delete_id_list.append(abnormal_list[i]['_id'])
+ for i in range(0, len(abnormal_list)): # 删除历史数据
+ delete_id_list.append(abnormal_list[i]['_id'])
+ delete_payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.GroupNotification_form_ID,
+ "data_ids": delete_id_list}
+
+ api_instance.entry_data_batch_delete(delete_payload)
except Exception as e:
- print(e)
+ error_task_logger.error(f"删除历史数据失败:{e}")
+ common_module.send_task_error(task_start_time, "短信数据支撑", str(e))
- # print(delete_id_list)
- delete_payload = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.GroupNotification_form_ID,
- "data_ids": delete_id_list}
+ data_commission = common_module.get_GroupNotification_details()
- api_instance.entry_data_batch_delete(delete_payload)
+ # 生成包含所有行转换后的字典列表
+ data_commission = [self.row_to_dict(row, self.field_mapping) for index, row in data_commission.iterrows()]
+ data_commission = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.GroupNotification_form_ID,
+ "data_list": data_commission}
-
- data_commission = common_module.get_GroupNotification_details()
-
- # 生成包含所有行转换后的字典列表
- data_commission = [self.row_to_dict(row, self.field_mapping) for index, row in data_commission.iterrows()]
- data_commission = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.GroupNotification_form_ID, "data_list": data_commission}
-
- result = api_instance.entry_data_batch_create(data_commission)
- # result_str = str(result)
- # print(result_str[:500])
-
- # 保存到Excel文件
- # output_path = r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细1.xlsx'
- # data_NGV_j.to_excel(output_path, index=False)
-
- end_time = datetime.datetime.now()
-
- time_diff = end_time - start_time
-
- # 打印天数、秒数和微秒数
- print(f"执行时间: {time_diff.days} 天, {time_diff.seconds} 秒, {time_diff.microseconds} 微秒")
- common_module.send_task_status(task_start_time, "短信数据支撑")
+ api_instance.entry_data_batch_create(data_commission)
+ common_module.send_task_status(task_start_time, "短信数据支撑")
+ except Exception as e:
+ error_task_logger.error(f"短信数据支撑失败:{e}")
+ common_module.send_task_error(task_start_time, "短信数据支撑", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
@@ -80,17 +70,18 @@ class importGroupNotificationData:
def fields(self):
self.field_mapping = {
- "公司id": "_widget_1743065201885",
- "是否启动短信功能": "_widget_1743065201886",
- "是否购买短信包": "_widget_1743065201887",
- "累计购买总数": "_widget_1743065201888",
- "累计发送成功总人数": "_widget_1743065201889",
- "剩余短信条数": "_widget_1743065201890",
- "第一次短信购买时间": "_widget_1743065201891",
- "最近一次短信购买时间": "_widget_1743065201892",
- "实付总金额": "_widget_1743065201893",
- "短信剩余量是否小于20%": "_widget_1743065201894"
- }
+ "公司id": "_widget_1743065201885",
+ "是否启动短信功能": "_widget_1743065201886",
+ "是否购买短信包": "_widget_1743065201887",
+ "累计购买总数": "_widget_1743065201888",
+ "累计发送成功总人数": "_widget_1743065201889",
+ "剩余短信条数": "_widget_1743065201890",
+ "第一次短信购买时间": "_widget_1743065201891",
+ "最近一次短信购买时间": "_widget_1743065201892",
+ "实付总金额": "_widget_1743065201893",
+ "短信剩余量是否小于20%": "_widget_1743065201894"
+ }
+
if __name__ == '__main__':
start = importGroupNotificationData()
diff --git a/back_ground_module/data_Support_Private_Mini_Program.py b/back_ground_module/data_Support_Private_Mini_Program.py
index f18c562..69185c3 100644
--- a/back_ground_module/data_Support_Private_Mini_Program.py
+++ b/back_ground_module/data_Support_Private_Mini_Program.py
@@ -5,7 +5,11 @@ from config import Config
from api import API
import pymysql # 使用 pymysql 替代 mysql.connector
from back_ground_module import CommonModule
+from log_config import configure_task_logger, configure_error_task_logger
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
start_time = datetime.datetime.now()
api_instance = API()
common_module = CommonModule()
@@ -19,43 +23,38 @@ class importSYXCXData:
def main(self):
task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- payload = {"api_key": Config.SaaS_Tasks_APP_ID,
- "entry_id": Config.SYXCX_form_ID,
- }
- abnormal_service = api_instance.entry_data_list(payload)
- abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
- for i in range(0,len(abnormal_list)): # 删除历史数据
+ try:
+ payload = {"api_key": Config.SaaS_Tasks_APP_ID,
+ "entry_id": Config.SYXCX_form_ID,
+ }
+ abnormal_service = api_instance.entry_data_list(payload)
+ abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
+
+ delete_id_list = []
try:
- delete_data = {"api_key": Config.SaaS_Tasks_APP_ID,
+ for i in range(0, len(abnormal_list)): # 删除历史数据
+ delete_id_list.append(abnormal_list[i]['_id'])
+ delete_payload = {"api_key": Config.SaaS_Tasks_APP_ID,
"entry_id": Config.SYXCX_form_ID,
- "data_id": abnormal_list[i]['_id']}
- api_instance.entry_data_delete(delete_data)
- except:
- pass
+ "data_id": delete_id_list}
+ api_instance.entry_data_batch_delete(delete_payload)
+ except Exception as e:
+ error_task_logger.error(f"删除私域小程序数据时出错: {e}")
+ common_module.send_task_error(task_start_time, "私域小程序数据支撑", str(e))
- data_SY = common_module.get_syxcx_details()
+ data_SY = common_module.get_syxcx_details()
- # 生成包含所有行转换后的字典列表
- data_SY = [self.row_to_dict(row, self.field_mapping) for index, row in data_SY.iterrows()]
- data_SY = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.SYXCX_form_ID, "data_list": data_SY}
-
- result = api_instance.entry_data_batch_create(data_SY)
- result_str = str(result)
- # print(result_str[:500])
+ # 生成包含所有行转换后的字典列表
+ data_SY = [self.row_to_dict(row, self.field_mapping) for index, row in data_SY.iterrows()]
+ data_SY = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.SYXCX_form_ID, "data_list": data_SY}
- # 保存到Excel文件
- # output_path = r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细1.xlsx'
- # data_NGV_j.to_excel(output_path, index=False)
-
- end_time = datetime.datetime.now()
-
- time_diff = end_time - start_time
-
- # 打印天数、秒数和微秒数
- print(f"执行时间: {time_diff.days} 天, {time_diff.seconds} 秒, {time_diff.microseconds} 微秒")
- common_module.send_task_status(task_start_time, "私域小程序数据支撑")
+ api_instance.entry_data_batch_create(data_SY)
+ common_module.send_task_status(task_start_time, "私域小程序数据支撑")
+ except Exception as e:
+ error_task_logger.error(f"私域小程序数据支撑执行时出错: {e}")
+ common_module.send_task_error(task_start_time, "私域小程序数据支撑", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
diff --git a/back_ground_module/data_monitor.py b/back_ground_module/data_monitor.py
index c3ff94a..c17b8d0 100644
--- a/back_ground_module/data_monitor.py
+++ b/back_ground_module/data_monitor.py
@@ -34,24 +34,6 @@ class Config:
RETRY_DELAY = 0.5
-# ---------------------- 日志配置 -----------------------
-# class Logger:
-# @staticmethod
-# def setup():
-# logging.basicConfig(
-# level=logging.INFO,
-# format='%(asctime)s - %(levelname)s - %(message)s',
-# handlers=[
-# logging.StreamHandler(),
-# logging.FileHandler(Config.LOG_FILE)
-# ]
-# )
-# return logging.getLogger(__name__)
-#
-#
-# logger = Logger.setup()
-
-
# ---------------------- 工具函数 -----------------------
class Utils:
@staticmethod
@@ -379,18 +361,23 @@ class DataMonitor(DataHandler):
def main(self):
import datetime
- task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- logger.info(f"=== 开始数据监控任务 ({self.execution_time}) ===")
+ task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ logger.info(f"=== 开始数据监控任务 ({self.execution_time}) ===")
- if Utils.is_first_run_today():
- success = self.run_daily_snapshot()
- else:
- success = self.run_hourly_check()
+ if Utils.is_first_run_today():
+ success = self.run_daily_snapshot()
+ else:
+ success = self.run_hourly_check()
- common_tools.send_task_status(task_start_time, "字段监控")
+ common_tools.send_task_status(task_start_time, "字段监控")
- logger.info("=== 数据监控任务完成 ===")
- return success
+ logger.info("=== 数据监控任务完成 ===")
+ return success
+ except Exception as e:
+ error_task_logger.error(f"数据监控任务发生异常: {e}")
+ common_tools.send_task_error(task_start_time, "字段监控", str(e))
+ return False
if __name__ == "__main__":
diff --git a/back_ground_module/get_process_time.py b/back_ground_module/get_process_time.py
index edc199d..31e52d1 100644
--- a/back_ground_module/get_process_time.py
+++ b/back_ground_module/get_process_time.py
@@ -1,16 +1,20 @@
from yd_api import YDAPI
-import pandas as pd
from tqdm import tqdm
import hashlib
from datetime import datetime, timedelta
import pandas as pd
import mysql.connector
-from mysql.connector import Error
import json
from back_ground_module import CommonModule
import numpy as np
from config import Config
+from log_config import configure_task_logger, configure_error_task_logger
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+
+# 获取已经配置好的错误任务日志记录器
+error_task_logger = configure_error_task_logger()
common_module = CommonModule()
# 初始化 API 实例和 Token
@@ -44,8 +48,6 @@ class TimeConsumingProcess():
PAGES_two = form_data_two.get('totalCount') // 100 + 1
- # # 手动控制小于3w
- # PAGES_two = 290
for a in tqdm(range(1, PAGES_two + 1)):
try:
form_data_two = api_instance.read_processes_instances(
@@ -55,12 +57,12 @@ class TimeConsumingProcess():
)
all_process_list = all_process_list + form_data_two.get("data")
except Exception as e:
- print(f"Error fetching page {a}: {e}")
+ logger.warning(f"获取流程实例数据时出错: {e}")
continue
return all_process_list
- def extract_approval_records(self, process_instances):
+ def extract_approval_records(self, process_instances: list):
"""提取每条流程的审批记录"""
all_data_list = []
for data in tqdm(process_instances, desc="处理流程实例"):
@@ -332,7 +334,6 @@ class TimeConsumingProcess():
# 4. 额外检查:确保时间格式正确
df = df[df['审批时间'].str.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$') | df['审批时间'].isnull()]
-
# 生成插入语句
try:
columns = ', '.join(df.columns)
@@ -358,28 +359,41 @@ class TimeConsumingProcess():
def main(self):
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # Step 1: 获取流程实例
- process_instances = self.fetch_process_data()
+ try:
+ logger.info("开始执行宜搭流程耗时写入BI任务。")
+ # Step 1: 获取流程实例
+ process_instances = self.fetch_process_data()
+ logger.info("获取流程实例成功。")
- # Step 2: 提取审批记录
- all_data_list = self.extract_approval_records(process_instances)
+ # Step 2: 提取审批记录
+ all_data_list = self.extract_approval_records(process_instances)
+ logger.info("提取审批记录成功。")
- # Step 3: 按 '提交申请' 分组
- result_groups = self.group_by_process(all_data_list)
+ # Step 3: 按 '提交申请' 分组
+ result_groups = self.group_by_process(all_data_list)
+ logger.info("按 '提交申请' 分组成功。")
- # Step 4: 转换为宽表
- df_final, max_steps = self.transform_to_wide_table(result_groups)
+ # Step 4: 转换为宽表
+ df_final, max_steps = self.transform_to_wide_table(result_groups)
+ logger.info("转换为宽表成功。")
- # Step 5: 对流程进行分类并保存结果
- df_final1 = self.classify_flows(df_final, max_steps)
+ # Step 5: 对流程进行分类并保存结果
+ df_final1 = self.classify_flows(df_final, max_steps)
+ logger.info("对流程进行分类并保存结果成功。")
- # Step 6: 耗时计算
- df_final2 = self.time_calculate(df_final1)
+ # Step 6: 耗时计算
+ df_final2 = self.time_calculate(df_final1)
+ logger.info("耗时计算成功。")
- # Step 7: 向BI写入数据
- self.write_to_bi(df_final2)
+ # Step 7: 向BI写入数据
+ self.write_to_bi(df_final2)
+ logger.info("向BI写入数据成功。")
- common_module.send_task_status(task_start_time, "宜搭流程耗时写入BI")
+ common_module.send_task_status(task_start_time, "宜搭流程耗时写入BI")
+ logger.info("宜搭流程耗时写入BI任务执行成功。")
+ except Exception as e:
+ error_task_logger.error(f"宜搭流程耗时写入BI执行出错: {e}")
+ common_module.send_task_error(task_start_time, "宜搭流程耗时写入BI", str(e))
if __name__ == '__main__':
diff --git a/back_ground_module/import_performance_data.py b/back_ground_module/import_performance_data.py
index 20420e4..6fc83f9 100644
--- a/back_ground_module/import_performance_data.py
+++ b/back_ground_module/import_performance_data.py
@@ -6,7 +6,11 @@ from api import API
import pymysql # 使用 pymysql 替代 mysql.connector
from back_ground_module import CommonModule
from tqdm import tqdm
+from log_config import configure_task_logger, configure_error_task_logger
+
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
start_time = datetime.datetime.now()
api_instance = API()
common_module = CommonModule()
@@ -107,40 +111,46 @@ class ImportPerformanceData:
def main(self):
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- self.load_all_data()
- # Step1:获取履约表数据
- df = common_module.get_perforamnce_details()
- print(df)
+ try:
+ self.load_all_data()
+ # Step1:获取履约表数据
+ df = common_module.get_perforamnce_details()
+ logger.info("数据获取完成")
- print("数据获取完成")
+ # Step2:清空现有数据
+ try:
+ id_list = [item["_id"] for item in self.performance_data_list]
- # Step2:清空现有数据
- id_list = [item["_id"] for item in self.performance_data_list]
+ delete_payload = {
+ "api_key": "675b900991ad2491c69389ca",
+ "entry_id": "68637c9818bc333fc14c30ad",
+ "data_ids": id_list
+ }
+ api_instance.entry_data_batch_delete(delete_payload)
+ logger.info("数据删除完成")
+ except Exception as e:
+ error_task_logger.error(f"数据删除失败: {e}")
+ common_module.send_task_error(task_start_time, "履约表数据支撑", str(e))
- delete_payload = {
- "api_key": "675b900991ad2491c69389ca",
- "entry_id": "68637c9818bc333fc14c30ad",
- "data_ids": id_list
- }
- api_instance.entry_data_batch_delete(delete_payload)
- print("数据删除完成")
+ # Step3:将数据写入简道云中
+ all_data = self.process_data(df)
- # Step3:将数据写入简道云中
- all_data = self.process_data(df)
+ # 分批处理,每批1000条
+ batch_size = 1000
+ for i in tqdm(range(0, len(all_data), batch_size)):
+ batch = all_data[i:i + batch_size]
+ payload = {
+ "api_key": "675b900991ad2491c69389ca",
+ "entry_id": "68637c9818bc333fc14c30ad",
+ "data_list": batch
+ }
+ api_instance.entry_data_batch_create(payload)
- # 分批处理,每批1000条
- batch_size = 1000
- for i in tqdm(range(0, len(all_data), batch_size)):
- batch = all_data[i:i + batch_size]
- payload = {
- "api_key": "675b900991ad2491c69389ca",
- "entry_id": "68637c9818bc333fc14c30ad",
- "data_list": batch
- }
- api_instance.entry_data_batch_create(payload)
-
- print("数据写入完成")
- common_module.send_task_status(task_start_time, "履约表数据支撑")
+ logger.info("简道云数据写入完成")
+ common_module.send_task_status(task_start_time, "履约表数据支撑")
+ except Exception as e:
+ error_task_logger.error(f"履约表数据支撑执行失败: {e}")
+ common_module.send_task_error(task_start_time, "履约表数据支撑", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
diff --git a/back_ground_module/indtall_event_dispatcher.py b/back_ground_module/indtall_event_dispatcher.py
index 6eff0d6..f46700c 100644
--- a/back_ground_module/indtall_event_dispatcher.py
+++ b/back_ground_module/indtall_event_dispatcher.py
@@ -81,67 +81,79 @@ class InstallEventDispatcher:
def main(self):
"""主函数"""
start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # 1.加载所有数据
- self.load_all_data()
- install_service_lead_list = self.install_service_lead
+ try:
+ # 1.加载所有数据
+ self.load_all_data()
+ install_service_lead_list = self.install_service_lead
- # 将list的字段映射为中文
- new_sign_abnormal_data = [
- self.reversed_dict(old_dict, self.reversed_field_mapping)
- for old_dict in install_service_lead_list
- ]
+ # 将list的字段映射为中文
+ new_sign_abnormal_data = [
+ self.reversed_dict(old_dict, self.reversed_field_mapping)
+ for old_dict in install_service_lead_list
+ ]
+ logger.info(f"加载数据完成")
- # 2.获取今日值班客服
- today_duty_staff = []
- for item in self.services_list:
- if item.get("_widget_1740117343937") == "开":
- today_duty_staff.append(item.get("_widget_1740042824214").get("username"))
+ # 2.获取今日值班客服
+ today_duty_staff = []
+ for item in self.services_list:
+ if item.get("_widget_1740117343937") == "开":
+ today_duty_staff.append(item.get("_widget_1740042824214").get("username"))
- count = len(today_duty_staff)
- if count == 0:
- print("今日值班客服为空,请检查数据")
- return
+ count = len(today_duty_staff)
+ if count == 0:
+ logger.warning(f"今日值班客服为空,请检查数据")
+ common_module.send_task_error(start_time, "安装服务历史派发", "今日值班客服为空")
+ return
+ logger.info(f"今日值班客服为:{today_duty_staff}")
- # 3.数据准备
- new_sign_abnormal_data = [item for item in new_sign_abnormal_data if item["线索状态"] != "已派发"]
+ # 3.数据准备
+ new_sign_abnormal_data = [item for item in new_sign_abnormal_data if item["线索状态"] != "已派发"]
- # 截取今日需要派发的数据
- new_sign_abnormal_data = new_sign_abnormal_data[:count]
+ # 截取今日需要派发的数据
+ new_sign_abnormal_data = new_sign_abnormal_data[:count]
- # 获取今日要派发数据的id
- id_list = [item["_id"] for item in new_sign_abnormal_data]
+ # 获取今日要派发数据的id
+ id_list = [item["_id"] for item in new_sign_abnormal_data]
- new_sign_abnormal_data = [
- self.row_to_dict(row, self.field_mapping)
- for row in new_sign_abnormal_data]
+ new_sign_abnormal_data = [
+ self.row_to_dict(row, self.field_mapping)
+ for row in new_sign_abnormal_data]
+ logger.info(f"数据准备完成")
- # 4.派发今日数据
- i = 0
- for item in new_sign_abnormal_data:
- item.update({"_widget_1744182647149": {"value":today_duty_staff[i]}})
+ # 4.派发今日数据
+ i = 0
+ for item in new_sign_abnormal_data:
+ item.update({"_widget_1744182647149": {"value": today_duty_staff[i]}})
- data = {
- 'api_key': "66f3a68c6e56814df2c6b1af",
- 'entry_id': "67f5dc467a9f5b2710da965a", # 安装服务意向表
- # 'entry_id': "6853c7cc512ffef038917440", # 测试表
- "data": item
- }
+ data = {
+ 'api_key': "66f3a68c6e56814df2c6b1af",
+ 'entry_id': "67f5dc467a9f5b2710da965a", # 安装服务意向表
+ # 'entry_id': "6853c7cc512ffef038917440", # 测试表
+ "data": item
+ }
- api_instance.data_batch_create(data)
+ res = api_instance.data_batch_create(data)
+ logger.info(f"数据派发:{res}")
+ i += 1
+ logger.info(f"数据派发完成")
- i += 1
+ # 5.修改原数据状态为已派发
+ for id in id_list:
+ data = {
+ 'api_key': "66f3a68c6e56814df2c6b1af",
+ 'entry_id': "68537b5e60a6295c6c09b464",
+ "data_id": id,
+ "data": {"_widget_1750301534577": {"value": "已派发"}}
+ }
+ res = api_instance.entry_data_update(data)
+ logger.info(f"数据状态修改:{res}")
+ logger.info(f"数据状态修改完成")
- # 5.修改原数据状态为已派发
- for id in id_list:
- data = {
- 'api_key': "66f3a68c6e56814df2c6b1af",
- 'entry_id': "68537b5e60a6295c6c09b464",
- "data_id": id,
- "data": {"_widget_1750301534577": {"value": "已派发"}}
- }
- api_instance.entry_data_update(data)
-
- common_module.send_task_status(start_time, "安装服务历史派发")
+ common_module.send_task_status(start_time, "安装服务历史派发")
+ logger.info("安装服务历史任务完成")
+ except Exception as e:
+ common_module.send_task_error(start_time, "安装服务历史派发", str(e))
+ error_task_logger.error(f"安装服务历史派发任务执行失败: {e}")
if __name__ == "__main__":
diff --git a/back_ground_module/new_dealer_service_order_to_bi.py b/back_ground_module/new_dealer_service_order_to_bi.py
index cdd805e..fb71d5f 100644
--- a/back_ground_module/new_dealer_service_order_to_bi.py
+++ b/back_ground_module/new_dealer_service_order_to_bi.py
@@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
-import pandas as pd
import datetime
from config import Config
from api import API
-import pymysql # 使用 pymysql 替代 mysql.connector
from back_ground_module import CommonModule
import os
import mysql.connector
@@ -28,6 +26,8 @@ output_dir = "output" # 设置输出目录
# 创建输出目录(如果不存在)
os.makedirs(output_dir, exist_ok=True)
+HS_DB_Config = Config.HS_DB_Config
+
class NewDealerServiceOrderToBI:
# 经销商新签服务单转BI
@@ -55,7 +55,7 @@ class NewDealerServiceOrderToBI:
'服务是否满意': '_widget_1743148999298', '服务不满意原因': '_widget_1743148999308',
'产品是否满意': '_widget_1743148999300', '产品不满意原因': '_widget_1743148999309',
# '上传评价图片': '_widget_1743148999310',
- '培训完成时间':'_widget_1754472835261',
+ '培训完成时间': '_widget_1754472835261',
'审核备注': '_widget_1743500862664',
'完成日期时间': '_widget_1753162835213', '流水号': '_widget_1753163217437',
'提交人': 'creator', '提交时间': 'createTime', '更新时间': 'updateTime'}
@@ -82,7 +82,8 @@ class NewDealerServiceOrderToBI:
df[col] = df[col].map(lambda x: x.get("name", "") if isinstance(x, dict) else "")
# 3.日期字段转为北京时间
- time_columns = ["订单支付时间", "开通时间", "系统到期时间", "完成日期时间", "提交时间", "更新时间","培训完成时间"]
+ time_columns = ["订单支付时间", "开通时间", "系统到期时间", "完成日期时间", "提交时间", "更新时间",
+ "培训完成时间"]
df[time_columns] = df[time_columns].apply(
lambda col: pd.to_datetime(col, errors='coerce')
@@ -93,13 +94,6 @@ class NewDealerServiceOrderToBI:
return df
def write_to_bi(self, df):
- # 数据库连接信息
- HS_DB_Config = {
- 'host': "f6-public.rwlb.rds.aliyuncs.com",
- 'user': "rw_operation_data_relay",
- 'password': "m+q5Z4%IVuF9bf",
- 'database': "f6operation_data_relay"
- }
table_name = "new_dealer_service_order_to_bi" # 替换为你的实际表名
# 建立数据库连接
@@ -122,7 +116,7 @@ class NewDealerServiceOrderToBI:
# 如果没有匹配的列,直接返回
if filtered_df.empty:
- print("DataFrame 中没有与数据库表结构匹配的列。")
+ logger.warning("DataFrame 中没有与数据库表结构匹配的列。")
return
# 筛选列之后,插入前处理 dict 类型
@@ -144,10 +138,12 @@ class NewDealerServiceOrderToBI:
cursor.execute(insert_sql, tuple(row))
connection.commit()
- print(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
+ logger.info(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
except Exception as e:
- print("写入数据库时发生错误:", e)
+ error_task_logger.error(f"写入数据库时发生错误:, {e}")
+ task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "经销商新签服务单转BI", str(e))
connection.rollback()
finally:
cursor.close()
@@ -158,13 +154,6 @@ class NewDealerServiceOrderToBI:
清空指定 MySQL 表的数据。
参数已写死在函数内部,直接调用即可。
"""
- # 数据库连接信息
- HS_DB_Config = {
- 'host': "f6-public.rwlb.rds.aliyuncs.com",
- 'user': "rw_operation_data_relay",
- 'password': "m+q5Z4%IVuF9bf",
- 'database': "f6operation_data_relay"
- }
table_name = "new_dealer_service_order_to_bi" # 要清空的表名
connection = None
@@ -182,36 +171,44 @@ class NewDealerServiceOrderToBI:
# 使用TRUNCATE清空表数据
cursor.execute(f"TRUNCATE TABLE {table_name}")
connection.commit()
-
- print(f"成功清空表 {table_name} 中的所有数据")
+ logger.info(f"成功清空表 {table_name} 中的所有数据")
except Error as e:
- print(f"清空表时发生错误: {e}")
+ logger.error(f"清空表时发生错误:{e}")
+ task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "经销商新签服务单转BI", str(e))
if connection and connection.is_connected():
connection.rollback()
finally:
if connection and connection.is_connected():
cursor.close()
connection.close()
- print("数据库连接已关闭")
+ logger.info("数据库连接已关闭")
def main(self):
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
- # step1: 获取数据
- self.load_all_data()
+ # step1: 获取数据
+ self.load_all_data()
+ logger.info(f"数据加载完成")
- # step2:数据处理
- df = self.data_process()
+ # step2:数据处理
+ df = self.data_process()
+ logger.info(f"数据处理完成")
+ # # step3:数据库删除
+ self.clear_table_data()
+ logger.info(f"数据库删除完成")
+ #
+ # # step4:数据写入BI
+ self.write_to_bi(df)
+ logger.info(f"数据写入BI完成")
- # # step3:数据库删除
- self.clear_table_data()
- #
- # # step4:数据写入BI
- self.write_to_bi(df)
-
- common_module.send_task_status(task_start_time, "经销商新签服务单转BI")
+ common_module.send_task_status(task_start_time, "经销商新签服务单转BI")
+ except Exception as e:
+ common_module.send_task_error(task_start_time, "经销商新签服务单转BI", str(e))
+ error_task_logger.error(f"经销商新签服务单转BI任务执行失败: {e}")
if __name__ == '__main__':
diff --git a/back_ground_module/revisit_all_information.py b/back_ground_module/revisit_all_information.py
index 1b0ade0..8ca32a8 100644
--- a/back_ground_module/revisit_all_information.py
+++ b/back_ground_module/revisit_all_information.py
@@ -1,9 +1,7 @@
import datetime
import os
import time
-
import requests
-
from api import API
import re
from back_ground_module import CommonModule
@@ -178,7 +176,6 @@ class RevisitAllInformation:
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e5107198ba1b20d5df3974"}
self.groupnotification = api_instance.entry_data_list(payload).get("data", [])
-
@staticmethod
def build_index(json_list):
index = {}
@@ -250,602 +247,604 @@ class RevisitAllInformation:
def main(self):
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ logger.info("开始执行任务")
+ global png_url, key, upload_key, feature_dict, UUid
+ self.load_all_data()
+ logger.info("数据加载完成")
+ self.date_list = common_module.get_holiday_list()
+ self.data_NGV_S = common_module.get_ngv_details(days_back=1).astype(str) # 获取data_NGV 并转为str
+ self.date_one = self.calculate_date_one(start_offset=0)
+ self.index = self.build_index(self.json_list)
+ self.saas_create_time_180 = 173 # 新签日期
+ self.saas_create_time_90 = 83 # 新签日期
- global png_url, key, upload_key
- self.load_all_data()
+ all_data = []
+ for i in range(0, self.date_one): # 从NGV总表过滤
+ # now_time = datetime.datetime.now() + datetime.timedelta(days=-76)
+ # now_time = now_time + datetime.timedelta(days=-i)
+ now_time = datetime.datetime.now() + datetime.timedelta(days=-i)
+ today = now_time + datetime.timedelta(days=-self.saas_create_time_180)
+ formatted_today_180 = today.strftime("%Y-%m-%d")
+ today = now_time + datetime.timedelta(days=-self.saas_create_time_90)
+ formatted_today_90 = today.strftime("%Y-%m-%d")
+ logger.info(f"开始处理{formatted_today_180}与{formatted_today_90}的数据")
- self.date_list = common_module.get_holiday_list()
- self.data_NGV_S = common_module.get_ngv_details(days_back=1).astype(str) # 获取data_NGV 并转为str
- self.date_one = self.calculate_date_one(start_offset=0)
- self.index = self.build_index(self.json_list)
- self.saas_create_time_180 = 173 # 新签日期
- self.saas_create_time_90 = 83 # 新签日期
+ data_NGV = self.data_NGV_S.copy()
- print("开始运行main")
- print(self.date_one)
- all_data=[]
- for i in range(0, self.date_one): # 从NGV总表过滤
- # now_time = datetime.datetime.now() + datetime.timedelta(days=-76)
- # now_time = now_time + datetime.timedelta(days=-i)
- now_time = datetime.datetime.now() + datetime.timedelta(days=-i)
- today = now_time + datetime.timedelta(days=-self.saas_create_time_180)
- formatted_today_180 = today.strftime("%Y-%m-%d")
- today = now_time + datetime.timedelta(days=-self.saas_create_time_90)
- formatted_today_90 = today.strftime("%Y-%m-%d")
- print("SaaS开户回访日期:", formatted_today_180, formatted_today_90)
+ def replace_values(series):
+ # 使用条件判断来进行替换
+ return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
- data_NGV = self.data_NGV_S.copy()
+ # 对整个DataFrame的所有列应用替换函数
+ data_NGV = data_NGV.apply(replace_values)
- def replace_values(series):
- # 使用条件判断来进行替换
- return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
+ # 定义优先级顺序
+ edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
+ customer_type_order = ["F", "E", "D", "C", "B", "A"] # 索引越小优先级越高
+ group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']
- # 对整个DataFrame的所有列应用替换函数
- data_NGV = data_NGV.apply(replace_values)
- # data_NGV.to_csv("dayinNGV.csv")
+ # 创建映射字典,并为不在列表中的值设置默认值
+ edition_map = {edition: idx for idx, edition in enumerate(edition_order)}
+ customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}
+ group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}
- # 定义优先级顺序
- edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
- customer_type_order = ["F", "E", "D", "C", "B", "A"] # 索引越小优先级越高
- group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']
+ # 添加用于排序的新列,并处理不在映射字典中的值
+ data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(
+ int) # 缺失值用最高优先级填充
+ data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(
+ int)
+ data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)
- # 创建映射字典,并为不在列表中的值设置默认值
- edition_map = {edition: idx for idx, edition in enumerate(edition_order)}
- customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}
- group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}
+ # 找到每组中 edition_rank 最小值对应的行
+ best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()
+ best_edition_rows = data_NGV.loc[best_edition_idx]
+ best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']
- # 添加用于排序的新列,并处理不在映射字典中的值
- data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(
- int) # 缺失值用最高优先级填充
- data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(int)
- data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)
- # data_NGV.to_csv("88855.csv")
+ # 找到每组中 customer_type_rank 最小值对应的行
+ best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()
+ best_customer_type_rows = data_NGV.loc[best_customer_type_idx]
+ best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(
+ lambda x: customer_type_order[x])
- # 找到每组中 edition_rank 最小值对应的行
- best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()
- best_edition_rows = data_NGV.loc[best_edition_idx]
- best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']
+ # 找到每组中 group_grade_rank 最小值对应的行
+ best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()
+ best_group_grade_rows = data_NGV.loc[best_group_grade_idx]
+ best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']
- # 找到每组中 customer_type_rank 最小值对应的行
- best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()
- best_customer_type_rows = data_NGV.loc[best_customer_type_idx]
- best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(
- lambda x: customer_type_order[x])
+ # 合并最佳值回到原数据集
+ best_values = (
+ best_edition_rows[['id_own_group', 'max_saas_edition']]
+ .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group',
+ how='outer')
+ .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')
+ )
- # 找到每组中 group_grade_rank 最小值对应的行
- best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()
- best_group_grade_rows = data_NGV.loc[best_group_grade_idx]
- best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']
+ # 将最佳值合并回原数据集
+ data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
- # 合并最佳值回到原数据集
- best_values = (
- best_edition_rows[['id_own_group', 'max_saas_edition']]
- .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group',
- how='outer')
- .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')
- )
+ condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件
- # 将最佳值合并回原数据集
- data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
+ ngvv2 = data_NGV[condition]
- condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件
+ data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中
+ data_NGV_V2['条件'] = (data_NGV_V2['org_type'] == "一般") & (data_NGV_V2['org_status'] == '留存') & (
+ data_NGV_V2['area_manager'] != '殷昊') & (
+ data_NGV_V2['area_manager'] != '孙玉蕾') & (
+ data_NGV_V2['is_main_org'] != 1)
+ data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2["条件"]]
+ # 步骤4: 过滤存在的记录
+ data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])
+ filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]
- ngvv2 = data_NGV[condition]
- # ngvv2.to_excel(r"C:\Users\Administrator.DESKTOP-7IC2USJ\Desktop\NGVV2.xlsx")
+ fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
+ # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))
- data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中
- data_NGV_V2['条件'] = (data_NGV_V2['org_type'] == "一般") & (data_NGV_V2['org_status'] == '留存') & (
- data_NGV_V2['area_manager'] != '殷昊') & (
- data_NGV_V2['area_manager'] != '孙玉蕾') & (
- data_NGV_V2['is_main_org'] != 1)
- data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2["条件"]]
- # 步骤4: 过滤存在的记录
- data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])
- filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]
+ fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}
+ filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)
+ filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)
- fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
- # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))
+ result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')
- fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}
- filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)
- filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)
+ data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
+ data_NGV['area_manager'] != '殷昊') & (
+ data_NGV['area_manager'] != '孙玉蕾') & (
+ data_NGV['is_main_org'] == "1")
- result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')
+ data_NGV = data_NGV.loc[data_NGV["条件"]]
- data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
- data_NGV['area_manager'] != '殷昊') & (
- data_NGV['area_manager'] != '孙玉蕾') & (
- data_NGV['is_main_org'] == "1")
-
- data_NGV = data_NGV.loc[data_NGV["条件"]]
-
- data_NGV = pd.concat([data_NGV, result], axis=0)
- print(len(data_NGV), "20250325")
-
- # 定义一个函数,根据 saas_create_time 字段的值设置阶段列和主要目的列的值
- def set_columns(row):
- if row['saas_create_time'] == formatted_today_180:
- row['跟进阶段'] = '新签后180天'
- row['主要目的'] = '关怀使用情况,邀约转介绍,跟进增购商机,识别首年续约风险,及时跟进提报。'
- elif row['saas_create_time'] == formatted_today_90:
- row['跟进阶段'] = '新签后90天'
- row['主要目的'] = '关怀使用情况,解答使用问题,强化培训,挖掘增购商机。'
- else:
- row['跟进阶段'] = "派发异常请联系数据组!" # 返回其他默认值
- row['主要目的'] = "派发异常请联系数据组!" # 返回其他默认值
- return row
-
- # 使用 apply 方法将函数应用到每一行
- data_NGV = data_NGV.apply(set_columns, axis=1)
-
- print("SaaS开户回访人数:", len(data_NGV))
- print(data_NGV)
-
- # 重置索引
- data_NGV = data_NGV.reset_index(drop=True)
-
- for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
- try:
- # print(row["org_code"]) # 数据验证
- # print(row["service_impl_principal"])
- # print(row["area_manager"])
- # print(row["technician"])
- payload_dict = {}
- saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
-
- NGV_roles = {
- 'relationship_manager': row['service_impl_principal'], # 运营负责人
- # 'relationship_manager': "张阳", # 运营负责人
- 'area_manager': row['area_manager'], # 区域经理
- 'technician': row['technician'], # 技术专家
- 'salesmen': row['salesmen'], # 销售负责人
- }
-
- for role, name in NGV_roles.items(): # 寻找对应的员工ID
- for row_item in self.staff_id_list:
- staff_id = self.get_staff_id(row_item, name)
- if staff_id:
- NGV_roles[role] = staff_id
- break # 找到后退出循环
- else:
- NGV_roles[role] = None # 如果没有找到对应的员工ID
-
- # 回访人员: 需确认 四年以下 technician
- if int(saas_use_year) < 4:
-
- relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
- ['relationship_manager',
- 'area_manager',
- 'technician', 'salesmen']]
-
- # 如果未找到运营负责人,则根据省市区派发给日常回访客服
- if not relationship_manager:
- relationship_manager = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )[0]
- if not technician:
- technician = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )[2]
-
- if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
- payload_dict.update({
- "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
- })
- else:
- payload_dict.update({
- "_widget_1734590278288": {"value": technician}, # 跟进人是技术专家
- })
+ data_NGV = pd.concat([data_NGV, result], axis=0)
+ logger.info(f"NGV过滤后长度:{len(data_NGV)}")
+ # 定义一个函数,根据 saas_create_time 字段的值设置阶段列和主要目的列的值
+ def set_columns(row):
+ if row['saas_create_time'] == formatted_today_180:
+ row['跟进阶段'] = '新签后180天'
+ row['主要目的'] = '关怀使用情况,邀约转介绍,跟进增购商机,识别首年续约风险,及时跟进提报。'
+ elif row['saas_create_time'] == formatted_today_90:
+ row['跟进阶段'] = '新签后90天'
+ row['主要目的'] = '关怀使用情况,解答使用问题,强化培训,挖掘增购商机。'
else:
- salesmen = [NGV_roles[role] for role in
- ['salesmen']]
- # 直接根据省市区派发给日常回访客服
- relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )
+ row['跟进阶段'] = "派发异常请联系数据组!" # 返回其他默认值
+ row['主要目的'] = "派发异常请联系数据组!" # 返回其他默认值
+ return row
+
+ # 使用 apply 方法将函数应用到每一行
+ data_NGV = data_NGV.apply(set_columns, axis=1)
+
+ logger.info(f"SaaS开户回访人数:{len(data_NGV)}")
+
+ # 重置索引
+ data_NGV = data_NGV.reset_index(drop=True)
+
+ for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
+ try:
+ payload_dict = {}
+ saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
+
+ NGV_roles = {
+ 'relationship_manager': row['service_impl_principal'], # 运营负责人
+ # 'relationship_manager': "张阳", # 运营负责人
+ 'area_manager': row['area_manager'], # 区域经理
+ 'technician': row['technician'], # 技术专家
+ 'salesmen': row['salesmen'], # 销售负责人
+ }
+
+ for role, name in NGV_roles.items(): # 寻找对应的员工ID
+ for row_item in self.staff_id_list:
+ staff_id = self.get_staff_id(row_item, name)
+ if staff_id:
+ NGV_roles[role] = staff_id
+ break # 找到后退出循环
+ else:
+ NGV_roles[role] = None # 如果没有找到对应的员工ID
+
+ # 回访人员: 需确认 四年以下 technician
+ if int(saas_use_year) < 4:
+
+ relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
+ ['relationship_manager',
+ 'area_manager',
+ 'technician', 'salesmen']]
+
+ # 如果未找到运营负责人,则根据省市区派发给日常回访客服
+ if not relationship_manager:
+ relationship_manager = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
+ )[0]
+ if not technician:
+ technician = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
+ )[2]
+
+ if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
+ payload_dict.update({
+ "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
+ })
+ else:
+ payload_dict.update({
+ "_widget_1734590278288": {"value": technician}, # 跟进人是技术专家
+ })
- if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
- payload_dict.update({
- "_widget_1734590278288": {"value": customer_service} # 跟进人是日常回访客服
- })
else:
- payload_dict.update({
- "_widget_1734590278288": {"value": technician} # 跟进人是技术专家
- })
-
- payload_dict.update({
- # "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
- "_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
- "_widget_1734590278290": {"value": area_manager}, # 区域经理
- "_widget_1734590278291": {"value": technician}, # 技术专家
- "_widget_1735290738545": {"value": salesmen} # 销售负责人
- })
-
- if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
- payload_dict.update({
- "_widget_1734590278288": {"value": "051612246035720178"}, # 跟进人是赵柄诚
- })
-
- # 输出结果
- print("SaaS开户回访人员:", relationship_manager or "未分配")
- print("SaaS技术专家:", technician or "未分配")
- print("SaaS区域经理:", area_manager or "未分配")
-
- # 判断权限唯一值
- # pattern = r'([\u4e00-\u9fa5]+)\('
- # match = re.search(pattern, row['max_group_grade'])
- # group_grade = match.group(1)
- group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
-
- if not row['saas_customer_type'] or row['saas_customer_type'] == 'NA' or row[
- 'saas_customer_type'] == 'None':
- row['saas_customer_type'] = "F"
-
- NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
- print("权限唯一值:", NGV_store_level_key)
-
- Billing = None
- for item in self.permissions_table:
- if NGV_store_level_key == item.get("_widget_1734056507963"): # 合并(等级-类型-分层)
- print("该门店开单的权限是:", item.get(item.get("_widget_1734055617039")))
- Billing = item.get("_widget_1734055617039") # 开单
- Service_Alerts = item.get("_widget_1734055617040") # 服务提醒
- membership = item.get("_widget_1734055617041") # 会员卡
- SMS = item.get("_widget_1734055617042") # 短信
- Public_domain_applets = item.get("_widget_1734055617043") # 公域小程序
- Private_domain_applets = item.get("_widget_1734055617044") # 私域小程序
- Test_sheet = item.get("_widget_1734055617045") # 检测单
- AI_poster = item.get("_widget_1734055617046") # AI海报
- Business_wallets = item.get("_widget_1734055617047") # 企业钱包
- Precision_marketing = item.get("_widget_1734055617049") # 精准营销
- Paid_memberships = item.get("_widget_1734055617051") # 付费会员
- business_WeCom = item.get("_widget_1734055617052") # 企业微信
- Insurance_policy_identification = item.get("_widget_1734055617053") # 保险单识别
- Insurance_bots = item.get("_widget_1734055617054") # 保险机器人
- Camera_pick_up = item.get("_widget_1734055617055") # 摄像头接车
- Camera_billing = item.get("_widget_1734055617056") # 摄像头开单
- Transparent_workshop = item.get("_widget_1734055617057") # 透明车间
- Cross_industry_cooperation = item.get("_widget_1734055617058") # 异业合作
- BI_Insights = item.get("_widget_1734055617059") # BI洞察
-
- payload_dict.update(
- {
- "_widget_1734073342350": {"value": Billing},
- "_widget_1735004315757": {"value": Service_Alerts},
- "_widget_1735004315756": {"value": membership},
- "_widget_1735004315755": {"value": SMS},
- "_widget_1735004315754": {"value": Public_domain_applets},
- "_widget_1735004315753": {"value": Private_domain_applets},
- "_widget_1735004315752": {"value": Test_sheet},
- "_widget_1735004315751": {"value": AI_poster},
- "_widget_1735004315750": {"value": Business_wallets},
- "_widget_1735004315749": {"value": Precision_marketing},
- "_widget_1735004315748": {"value": Paid_memberships},
- "_widget_1735004315747": {"value": business_WeCom},
- "_widget_1735004315746": {"value": Insurance_policy_identification},
- "_widget_1735004315745": {"value": Insurance_bots},
- "_widget_1735004315744": {"value": Camera_pick_up},
- "_widget_1735004315743": {"value": Camera_billing},
- "_widget_1735004315742": {"value": Transparent_workshop},
- "_widget_1735004315741": {"value": Cross_industry_cooperation},
- "_widget_1734073342352": {"value": BI_Insights},
-
- }
+ salesmen = [NGV_roles[role] for role in
+ ['salesmen']]
+ # 直接根据省市区派发给日常回访客服
+ relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
)
- feature_dict = {
- "开单": "_widget_1734073342350",
- "服务提醒": "_widget_1735004315757",
- "会员卡": "_widget_1735004315756",
- "短信": "_widget_1735004315755",
- "公域小程序": "_widget_1735004315754",
- "私域小程序": "_widget_1735004315753",
- "检测单": "_widget_1735004315752",
- "AI海报": "_widget_1735004315751",
- "企业钱包": "_widget_1735004315750",
- "精准营销": "_widget_1735004315749",
- "付费会员": "_widget_1735004315748",
- "企业微信": "_widget_1735004315747",
- "保险单识别": "_widget_1735004315746",
- "保险机器人": "_widget_1735004315745",
- "摄像头接车": "_widget_1735004315744",
- "摄像头开单": "_widget_1735004315743",
- "透明车间": "_widget_1735004315742",
- "异业合作": "_widget_1735004315741",
- "BI洞察": "_widget_1734073342352",
+ if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
+ payload_dict.update({
+ "_widget_1734590278288": {"value": customer_service} # 跟进人是日常回访客服
+ })
+ else:
+ payload_dict.update({
+ "_widget_1734590278288": {"value": technician} # 跟进人是技术专家
+ })
- }
- # _widget_1735527329557 下次是否推荐
- for new_item in self.get_feature_usage:
- for feature_module, feature_value in feature_dict.items(): # 模块
- if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
- "_widget_1735527329557") == "否" and new_item.get(
- "_widget_1735280720550") == \
- row["id_own_org"]: # 下次是否推荐 功能使用情况表
- print(f"{feature_value}进行了更改")
- payload_dict.update({f"{feature_value}": {"value": "×"}})
+ payload_dict.update({
+ # "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
+ "_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
+ "_widget_1734590278290": {"value": area_manager}, # 区域经理
+ "_widget_1734590278291": {"value": technician}, # 技术专家
+ "_widget_1735290738545": {"value": salesmen} # 销售负责人
+ })
- if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
- "_widget_1736414617462") == "否" and new_item.get(
- "_widget_1735280720550") == \
- row["id_own_org"]: # 下次是否跟进
- print(f"{feature_value}进行了更改")
- payload_dict.update({f"{feature_value}": {"value": "×"}})
+ if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
+ payload_dict.update({
+ "_widget_1734590278288": {"value": "051612246035720178"}, # 跟进人是赵柄诚
+ })
- fields_to_check = {
- "_widget_1735004315763": Billing, # 开单
- "_widget_1735106258016": Service_Alerts, # 服务提醒
- "_widget_1735106258036": membership, # 会员卡
- "_widget_1735106258086": SMS, # 短信
- "_widget_1735106258112": Public_domain_applets, # 公域小程序
- "_widget_1735106258141": Private_domain_applets, # 私域小程序
- "_widget_1735107354648": Test_sheet, # 检测单
- "_widget_1735107354725": AI_poster, # AI海报
- "_widget_1735107354811": Business_wallets, # 企业钱包
- "_widget_1735107354906": Precision_marketing, # 精准营销
- "_widget_1735107354980": Paid_memberships, # 付费会员
- "_widget_1735107355093": business_WeCom, # 企业微信
- "_widget_1735107355143": Insurance_policy_identification, # 保险单识别
- "_widget_1735107355235": Insurance_bots, # 保险机器人
- "_widget_1735107355333": Camera_pick_up, # 摄像头接车
- "_widget_1735107355392": Camera_billing, # 摄像头开单
- "_widget_1735107355502": Transparent_workshop, # 透明车间
- "_widget_1735107355618": Cross_industry_cooperation, # 异业合作
- "_widget_1735107355740": BI_Insights # BI洞察
- }
+ # 输出结果
+ logger.info(f"SaaS开户回访人员:{relationship_manager}")
+ logger.info(f"SaaS技术专家:{technician}")
+ logger.info(f"SaaS区域经理:{area_manager}")
- # 遍历每个字段,检查其值并更新payload_dict
- for widget_id, field_name in fields_to_check.items():
- if field_name == "√":
- payload_dict.update({widget_id: {"value": "是"}})
+ # 判断权限唯一值
+ group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
- break
+ if not row['saas_customer_type'] or row['saas_customer_type'] == 'NA' or row[
+ 'saas_customer_type'] == 'None':
+ row['saas_customer_type'] = "F"
- if not Billing:
- print(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
+ NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
+ logger.info(f"权限唯一值:{NGV_store_level_key}")
- if row["active_status_fmt"] == "活跃": # 开单 是否使用
- payload_dict.update({"_widget_1735004315765": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735004315765": {"value": "否"}})
- try:
- if row["saas_edition_fmt"] not in ["基础版", "入门版"]: # 会员卡 是否拥有
- payload_dict.update({"_widget_1735106258036": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735106258036": {"value": "否"}})
- except Exception as e:
- print(f"会员卡识别:Error finding customer service: {e}")
- try:
- if row["card_bill_day_count_last_30_day"] != "0": # 会员卡 是否使用
- payload_dict.update({"_widget_1735106258038": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735106258038": {"value": "否"}})
- except Exception as e:
- print(f"会员卡识别:Error finding customer service: {e}")
- # print(self.service_remind.get("_widget_1735112637045"))
- payload_dict["_widget_1735106258018"] = {"value": "否"}
+ Billing = None
+ for item in self.permissions_table:
+ if NGV_store_level_key == item.get("_widget_1734056507963"): # 合并(等级-类型-分层)
+ print("该门店开单的权限是:", item.get(item.get("_widget_1734055617039")))
+ Billing = item.get("_widget_1734055617039") # 开单
+ Service_Alerts = item.get("_widget_1734055617040") # 服务提醒
+ membership = item.get("_widget_1734055617041") # 会员卡
+ SMS = item.get("_widget_1734055617042") # 短信
+ Public_domain_applets = item.get("_widget_1734055617043") # 公域小程序
+ Private_domain_applets = item.get("_widget_1734055617044") # 私域小程序
+ Test_sheet = item.get("_widget_1734055617045") # 检测单
+ AI_poster = item.get("_widget_1734055617046") # AI海报
+ Business_wallets = item.get("_widget_1734055617047") # 企业钱包
+ Precision_marketing = item.get("_widget_1734055617049") # 精准营销
+ Paid_memberships = item.get("_widget_1734055617051") # 付费会员
+ business_WeCom = item.get("_widget_1734055617052") # 企业微信
+ Insurance_policy_identification = item.get("_widget_1734055617053") # 保险单识别
+ Insurance_bots = item.get("_widget_1734055617054") # 保险机器人
+ Camera_pick_up = item.get("_widget_1734055617055") # 摄像头接车
+ Camera_billing = item.get("_widget_1734055617056") # 摄像头开单
+ Transparent_workshop = item.get("_widget_1734055617057") # 透明车间
+ Cross_industry_cooperation = item.get("_widget_1734055617058") # 异业合作
+ BI_Insights = item.get("_widget_1734055617059") # BI洞察
+
+ payload_dict.update(
+ {
+ "_widget_1734073342350": {"value": Billing},
+ "_widget_1735004315757": {"value": Service_Alerts},
+ "_widget_1735004315756": {"value": membership},
+ "_widget_1735004315755": {"value": SMS},
+ "_widget_1735004315754": {"value": Public_domain_applets},
+ "_widget_1735004315753": {"value": Private_domain_applets},
+ "_widget_1735004315752": {"value": Test_sheet},
+ "_widget_1735004315751": {"value": AI_poster},
+ "_widget_1735004315750": {"value": Business_wallets},
+ "_widget_1735004315749": {"value": Precision_marketing},
+ "_widget_1735004315748": {"value": Paid_memberships},
+ "_widget_1735004315747": {"value": business_WeCom},
+ "_widget_1735004315746": {"value": Insurance_policy_identification},
+ "_widget_1735004315745": {"value": Insurance_bots},
+ "_widget_1735004315744": {"value": Camera_pick_up},
+ "_widget_1735004315743": {"value": Camera_billing},
+ "_widget_1735004315742": {"value": Transparent_workshop},
+ "_widget_1735004315741": {"value": Cross_industry_cooperation},
+ "_widget_1734073342352": {"value": BI_Insights},
+
+ }
+ )
+
+ feature_dict = {
+ "开单": "_widget_1734073342350",
+ "服务提醒": "_widget_1735004315757",
+ "会员卡": "_widget_1735004315756",
+ "短信": "_widget_1735004315755",
+ "公域小程序": "_widget_1735004315754",
+ "私域小程序": "_widget_1735004315753",
+ "检测单": "_widget_1735004315752",
+ "AI海报": "_widget_1735004315751",
+ "企业钱包": "_widget_1735004315750",
+ "精准营销": "_widget_1735004315749",
+ "付费会员": "_widget_1735004315748",
+ "企业微信": "_widget_1735004315747",
+ "保险单识别": "_widget_1735004315746",
+ "保险机器人": "_widget_1735004315745",
+ "摄像头接车": "_widget_1735004315744",
+ "摄像头开单": "_widget_1735004315743",
+ "透明车间": "_widget_1735004315742",
+ "异业合作": "_widget_1735004315741",
+ "BI洞察": "_widget_1734073342352",
+
+ }
+ # _widget_1735527329557 下次是否推荐
+ for new_item in self.get_feature_usage:
+ for feature_module, feature_value in feature_dict.items(): # 模块
+ if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
+ "_widget_1735527329557") == "否" and new_item.get(
+ "_widget_1735280720550") == \
+ row["id_own_org"]: # 下次是否推荐 功能使用情况表
+ logger.info(f"{feature_value}进行了更改")
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+
+ if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
+ "_widget_1736414617462") == "否" and new_item.get(
+ "_widget_1735280720550") == \
+ row["id_own_org"]: # 下次是否跟进
+ logger.info(f"{feature_value}进行了更改")
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+
+ fields_to_check = {
+ "_widget_1735004315763": Billing, # 开单
+ "_widget_1735106258016": Service_Alerts, # 服务提醒
+ "_widget_1735106258036": membership, # 会员卡
+ "_widget_1735106258086": SMS, # 短信
+ "_widget_1735106258112": Public_domain_applets, # 公域小程序
+ "_widget_1735106258141": Private_domain_applets, # 私域小程序
+ "_widget_1735107354648": Test_sheet, # 检测单
+ "_widget_1735107354725": AI_poster, # AI海报
+ "_widget_1735107354811": Business_wallets, # 企业钱包
+ "_widget_1735107354906": Precision_marketing, # 精准营销
+ "_widget_1735107354980": Paid_memberships, # 付费会员
+ "_widget_1735107355093": business_WeCom, # 企业微信
+ "_widget_1735107355143": Insurance_policy_identification, # 保险单识别
+ "_widget_1735107355235": Insurance_bots, # 保险机器人
+ "_widget_1735107355333": Camera_pick_up, # 摄像头接车
+ "_widget_1735107355392": Camera_billing, # 摄像头开单
+ "_widget_1735107355502": Transparent_workshop, # 透明车间
+ "_widget_1735107355618": Cross_industry_cooperation, # 异业合作
+ "_widget_1735107355740": BI_Insights # BI洞察
+ }
+
+ # 遍历每个字段,检查其值并更新payload_dict
+ for widget_id, field_name in fields_to_check.items():
+ if field_name == "√":
+ payload_dict.update({widget_id: {"value": "是"}})
- for item in self.service_remind:
- if row["id_own_group"] == item.get("_widget_1735112637043"):
- if int(item.get("_widget_1735112637045")) < 180 and int(
- item.get("_widget_1735112637046")) == 1: # 服务提醒 是否使用
- payload_dict.update({"_widget_1735106258018": {"value": "是"}})
- break
- elif int(item.get("_widget_1735112637048")) > 0:
- payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- keys_to_check = [
- "_widget_1735113110155"
- ] # 智能检测 是否使用
+ if not Billing:
+ logger.warning(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
- # 初始化默认值为"否"
- payload_dict["_widget_1735107354650"] = {"value": "否"}
-
- # 检查每个键,如果有一个大于0,则更新为"是"并停止检查
- for key in keys_to_check:
- for item in self.Smart_detection:
- if row["id_own_org"] == item.get("_widget_1735113110147"):
- if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况
- payload_dict["_widget_1735107354650"]["value"] = "是"
- break
-
- # 近30天业务单量=0 则其它所有模块均不推荐
- try:
- for feature_module, feature_value in feature_dict.items(): # 模块
- if row["bill_count_last_30_day"] == '0' and payload_dict[feature_value]["value"] == '△':
- payload_dict.update({f"{feature_value}": {"value": "×"}})
- except Exception as e:
- print(f"不开单识别:Error finding customer service: {e}")
- # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐
- try:
- if row["org_code"] in self.widget_list:
- payload_dict.update({'_widget_1735004315746': {"value": "△"}})
- except Exception as e:
- print(f"保单识别:Error finding customer service: {e}")
- # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
- try:
- for item in self.private_domain:
- if row["id_own_group"] == item.get("_widget_1742795002375"): # 公司id
- if int(item.get("_widget_1742795002379")) > 0: # 上架商品数
- payload_dict.update({"_widget_1735106258143": {"value": "是"}}) # DX:是否拥有
- break
- else:
- payload_dict.update({"_widget_1735106258143": {"value": "否"}}) # DX:是否拥有
- break
- except Exception as e:
- print(f"私域小程序:Error finding customer service: {e}")
- try:
- high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']
- if row["saas_edition_fmt"] in high_version:
- payload_dict.update({'_widget_1735106258141': {"value": "是"}}) # SYXCX:是否拥有
+ if row["active_status_fmt"] == "活跃": # 开单 是否使用
+ payload_dict.update({"_widget_1735004315765": {"value": "是"}})
else:
- payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
- except Exception as e:
- print(f"私域小程序:Error finding customer service: {e}")
+ payload_dict.update({"_widget_1735004315765": {"value": "否"}})
- # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
- try:
- for item in self.public_domain:
- if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
- if int(item.get("_widget_1742784257509")) == 1: # 发布商品数量
- payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
+ try:
+ if row["saas_edition_fmt"] not in ["基础版", "入门版"]: # 会员卡 是否拥有
+ payload_dict.update({"_widget_1735106258036": {"value": "是"}})
+ else:
+ payload_dict.update({"_widget_1735106258036": {"value": "否"}})
+ except Exception as e:
+ error_task_logger.error(f"会员卡拥有识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-会员卡拥有识别", str(e))
+ try:
+ if row["card_bill_day_count_last_30_day"] != "0": # 会员卡 是否使用
+ payload_dict.update({"_widget_1735106258038": {"value": "是"}})
+ else:
+ payload_dict.update({"_widget_1735106258038": {"value": "否"}})
+ except Exception as e:
+ error_task_logger.error(f"会员卡使用识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-会员卡使用识别", str(e))
+
+ payload_dict["_widget_1735106258018"] = {"value": "否"}
+
+ for item in self.service_remind:
+ if row["id_own_group"] == item.get("_widget_1735112637043"):
+ if int(item.get("_widget_1735112637045")) < 180 and int(
+ item.get("_widget_1735112637046")) == 1: # 服务提醒 是否使用
+ payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- else:
- payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
+ elif int(item.get("_widget_1735112637048")) > 0:
+ payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- except Exception as e:
- print(f"公域小程序:Error finding customer service: {e}")
- try:
- if row["id_own_org"] in self.public_domain_list:
- payload_dict.update({'_widget_1735106258112': {"value": "是"}}) # GYXCX:是否拥有
- else:
- payload_dict.update({'_widget_1735106258112': {"value": "否"}}) # GYXCX:是否拥有
- except Exception as e:
- print(f"公域小程序:Error finding customer service: {e}")
- # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字
- try:
- if row["id_own_org"] in self.different_industries_list:
- payload_dict.update({'_widget_1735107355618': {"value": "是"}}) # YYHZ:是否拥有
- else:
- payload_dict.update({'_widget_1735107355618': {"value": "否"}}) # YYHZ:是否拥有
- except Exception as e:
- print(f"异业合作:Error finding customer service: {e}")
- # 短信:根据是否启动短信功能判断是否拥有,根据
- try:
- for item in self.groupnotification:
- if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
- if int(item.get("_widget_1743065201886")) == 1: # 是否启动短信功能
- payload_dict.update({"_widget_1735106258086": {"value": "是"}}) # DX:是否拥有
- break
- else:
- payload_dict.update({"_widget_1735106258086": {"value": "否"}}) # DX:是否拥有
- break
- except Exception as e:
- print(f"短信:Error finding customer service: {e}")
+ keys_to_check = [
+ "_widget_1735113110155"
+ ] # 智能检测 是否使用
- try:
- for item in self.groupnotification:
- if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
- if int(item.get("_widget_1743065201889")) > 0: # 累计发送成功总人数
- payload_dict.update({"_widget_1735106258088": {"value": "是"}}) # DX:是否使用
- break
- else:
- payload_dict.update({"_widget_1735106258088": {"value": "否"}}) # DX:是否使用
- break
- except Exception as e:
- print(f"短信:Error finding customer service: {e}")
+ # 初始化默认值为"否"
+ payload_dict["_widget_1735107354650"] = {"value": "否"}
- NGV_data_id = None
- # 获取关联数据
- for NGV_Data in self.NGV_data_list:
- # NGV_Data = NGV_Data.get("data")
- if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
- NGV_data_id = NGV_Data.get("_id")
- print(NGV_data_id)
- try:
- png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
- except:
- png_url = ""
- print(png_url)
- if not NGV_data_id:
- print("未找到数据ID")
+ # 检查每个键,如果有一个大于0,则更新为"是"并停止检查
+ for key in keys_to_check:
+ for item in self.Smart_detection:
+ if row["id_own_org"] == item.get("_widget_1735113110147"):
+ if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况
+ payload_dict["_widget_1735107354650"]["value"] = "是"
+ break
- distribution_date = datetime.datetime.now(datetime.timezone.utc)
- distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
+ # 近30天业务单量=0 则其它所有模块均不推荐
+ try:
+ for feature_module, feature_value in feature_dict.items(): # 模块
+ if row["bill_count_last_30_day"] == '0' and payload_dict[feature_value]["value"] == '△':
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+ except Exception as e:
+ error_task_logger.error(f"不开单识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-不开单识别", str(e))
+ # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐
+ try:
+ if row["org_code"] in self.widget_list:
+ payload_dict.update({'_widget_1735004315746': {"value": "△"}})
+ except Exception as e:
+ error_task_logger.error(f"保单识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-保单识别", str(e))
+ # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
+ try:
+ for item in self.private_domain:
+ if row["id_own_group"] == item.get("_widget_1742795002375"): # 公司id
+ if int(item.get("_widget_1742795002379")) > 0: # 上架商品数
+ payload_dict.update({"_widget_1735106258143": {"value": "是"}}) # DX:是否拥有
+ break
+ else:
+ payload_dict.update({"_widget_1735106258143": {"value": "否"}}) # DX:是否拥有
+ break
+ except Exception as e:
+ error_task_logger.error(f"小程序识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-小程序识别", str(e))
+ try:
+ high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']
+ if row["saas_edition_fmt"] in high_version:
+ payload_dict.update({'_widget_1735106258141': {"value": "是"}}) # SYXCX:是否拥有
+ else:
+ payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"私域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time,"手动添加日常回访-私域小程序",str(e))
- upload_key = None
- UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
- if png_url:
- save_dir = "sampleCloud" # 设置输出目录
+ # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
+ try:
+ for item in self.public_domain:
+ if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
+ if int(item.get("_widget_1742784257509")) == 1: # 发布商品数量
+ payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
+ break
+ else:
+ payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
+ break
+ except Exception as e:
+ error_task_logger.error(f"公域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-公域小程序", str(e))
- # 创建输出目录(如果不存在)
- import os
+ try:
+ if row["id_own_org"] in self.public_domain_list:
+ payload_dict.update({'_widget_1735106258112': {"value": "是"}}) # GYXCX:是否拥有
+ else:
+ payload_dict.update({'_widget_1735106258112': {"value": "否"}}) # GYXCX:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"公域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-公域小程序", str(e))
- os.makedirs(save_dir, exist_ok=True)
+ # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字
+ try:
+ if row["id_own_org"] in self.different_industries_list:
+ payload_dict.update({'_widget_1735107355618': {"value": "是"}}) # YYHZ:是否拥有
+ else:
+ payload_dict.update({'_widget_1735107355618': {"value": "否"}}) # YYHZ:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"异业合作:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-异业合作", str(e))
+ # 短信:根据是否启动短信功能判断是否拥有,根据
+ try:
+ for item in self.groupnotification:
+ if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
+ if int(item.get("_widget_1743065201886")) == 1: # 是否启动短信功能
+ payload_dict.update({"_widget_1735106258086": {"value": "是"}}) # DX:是否拥有
+ break
+ else:
+ payload_dict.update({"_widget_1735106258086": {"value": "否"}}) # DX:是否拥有
+ break
+ except Exception as e:
+ error_task_logger.error(f"短信是否使用:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-短信是否使用", str(e))
- save_path = fr'{save_dir}\png\{time.strftime("%Y%m%d%H%M%S", time.localtime())}.png'
+ try:
+ for item in self.groupnotification:
+ if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
+ if int(item.get("_widget_1743065201889")) > 0: # 累计发送成功总人数
+ payload_dict.update({"_widget_1735106258088": {"value": "是"}}) # DX:是否使用
+ break
+ else:
+ payload_dict.update({"_widget_1735106258088": {"value": "否"}}) # DX:是否使用
+ break
+ except Exception as e:
+ error_task_logger.error(f"短信是否使用:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-短信是否使用", str(e))
- RevisitAllInformation.download_url_content(png_url, save_path)
+ NGV_data_id = None
+ # 获取关联数据
+ for NGV_Data in self.NGV_data_list:
+ # NGV_Data = NGV_Data.get("data")
+ if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
+ NGV_data_id = NGV_Data.get("_id")
+ logger.info(f"关联数据数据id:{NGV_data_id}")
+ try:
+ png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
+ except:
+ png_url = ""
+ logger.info(f"关联数据图片:{png_url}")
+ if not NGV_data_id:
+ logger.warning("未找到数据ID")
- up_data = api_instance.get_upload_token(
- {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b9c63925cd404038a6b86",
- "transaction_id": UUid})
+ distribution_date = datetime.datetime.now(datetime.timezone.utc)
+ distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
- upload_url = up_data.get("upload_url")
- upload_token = up_data.get("upload_token")
+ upload_key = None
+ UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
+ if png_url:
+ save_dir = "sampleCloud" # 设置输出目录
- upload_result = api_instance.upload_file(
- {"upload_url": upload_url, "upload_token": upload_token, "file_path": save_path})
- upload_key = upload_result.get("key")
- # print("已上传文件")
- # print(upload_result)
+ # 创建输出目录(如果不存在)
+ import os
- # print(upload_key)
+ os.makedirs(save_dir, exist_ok=True)
- payload_dict.update({
- "_widget_1734590278279": {"value": row["group_name"]}, # 公司名称
- "_widget_1735112931760": {"value": row["id_own_group"]}, # 公司id
- "_widget_1735112931761": {"value": row["id_own_org"]}, # 门店id
- "_widget_1734590278281": {"value": row['org_name']}, # 门店名称
- "_widget_1734590278292": {"value": row["跟进阶段"]}, # 跟进阶段
- "_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
- "_widget_1742548684369": {"value": row['主要目的']}, # 主要目的
- "_widget_1734590278266": {"value": row['region_name']}, # 大区
- "_widget_1734590278285": {"value": row['branch_name']}, # 小区
- "_widget_1734590278284": {"value": row['province_name']}, # 省
- "_widget_1734590278283": {"value": row['city_name']}, # 市
- "_widget_1734590278282": {"value": row['area_name']}, # 区
- "_widget_1734590278278": {"value": row['saas_customer_type']}, # 门店分层
- "_widget_1734590278277": {"value": row['group_grade']}, # 公司等级
- "_widget_1734590278276": {"value": row['limit_user_type']}, # 限制账户类型
- "_widget_1734590278275": {"value": row['active_user_type']}, # 有效账户类型
- "_widget_1734590278274": {"value": row['saas_version']}, # ERP操作模式
- "_widget_1734590278273": {"value": row['saas_use_year']}, # 使用时长
- "_widget_1734590278272": {"value": row['org_stage']}, # 门店阶段
- "_widget_1734590278271": {"value": row['manage_model']}, # 经营模式
- "_widget_1734590278267": {"value": row['contacts']}, # 联系人
- "_widget_1734590278287": {"value": row['contact_mobile']}, # 联系手机号
- "_widget_1734590278286": {"value": row['saas_edition_fmt']}, # SaaS版本
- "_widget_1734590278280": {"value": row['org_code']}, # 门店编码
- "_widget_1735096489244": {"value": distribution_date}, # 派发时间
- "_widget_1742895342914": {"value": row['business_scope_fmt']}, # 经营范围
- "_widget_1742895342915": {"value": row['station_number']}, # 工位数
- "_widget_1742895342916": {"value": [upload_key]} # 门头照片
- })
- # 以上部分删除重新从日常回访新签回访复制 , 增加all_data=[] ,去除日期条件过滤
- all_data.append(payload_dict)
+ save_path = fr'{save_dir}\png\{time.strftime("%Y%m%d%H%M%S", time.localtime())}.png'
+
+ RevisitAllInformation.download_url_content(png_url, save_path)
+ logger.info(f"已保存图片到 {save_path}。")
+
+ up_data = api_instance.get_upload_token(
+ {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b9c63925cd404038a6b86",
+ "transaction_id": UUid})
+
+ upload_url = up_data.get("upload_url")
+ upload_token = up_data.get("upload_token")
+
+ upload_result = api_instance.upload_file(
+ {"upload_url": upload_url, "upload_token": upload_token, "file_path": save_path})
+ upload_key = upload_result.get("key")
+ logger.info("已上传文件")
+
+ payload_dict.update({
+ "_widget_1734590278279": {"value": row["group_name"]}, # 公司名称
+ "_widget_1735112931760": {"value": row["id_own_group"]}, # 公司id
+ "_widget_1735112931761": {"value": row["id_own_org"]}, # 门店id
+ "_widget_1734590278281": {"value": row['org_name']}, # 门店名称
+ "_widget_1734590278292": {"value": row["跟进阶段"]}, # 跟进阶段
+ "_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
+ "_widget_1742548684369": {"value": row['主要目的']}, # 主要目的
+ "_widget_1734590278266": {"value": row['region_name']}, # 大区
+ "_widget_1734590278285": {"value": row['branch_name']}, # 小区
+ "_widget_1734590278284": {"value": row['province_name']}, # 省
+ "_widget_1734590278283": {"value": row['city_name']}, # 市
+ "_widget_1734590278282": {"value": row['area_name']}, # 区
+ "_widget_1734590278278": {"value": row['saas_customer_type']}, # 门店分层
+ "_widget_1734590278277": {"value": row['group_grade']}, # 公司等级
+ "_widget_1734590278276": {"value": row['limit_user_type']}, # 限制账户类型
+ "_widget_1734590278275": {"value": row['active_user_type']}, # 有效账户类型
+ "_widget_1734590278274": {"value": row['saas_version']}, # ERP操作模式
+ "_widget_1734590278273": {"value": row['saas_use_year']}, # 使用时长
+ "_widget_1734590278272": {"value": row['org_stage']}, # 门店阶段
+ "_widget_1734590278271": {"value": row['manage_model']}, # 经营模式
+ "_widget_1734590278267": {"value": row['contacts']}, # 联系人
+ "_widget_1734590278287": {"value": row['contact_mobile']}, # 联系手机号
+ "_widget_1734590278286": {"value": row['saas_edition_fmt']}, # SaaS版本
+ "_widget_1734590278280": {"value": row['org_code']}, # 门店编码
+ "_widget_1735096489244": {"value": distribution_date}, # 派发时间
+ "_widget_1742895342914": {"value": row['business_scope_fmt']}, # 经营范围
+ "_widget_1742895342915": {"value": row['station_number']}, # 工位数
+ "_widget_1742895342916": {"value": [upload_key]} # 门头照片
+ })
+ # 以上部分删除重新从日常回访新签回访复制 , 增加all_data=[] ,去除日期条件过滤
+ all_data.append(payload_dict)
- except:
- pass
- break
- routine_follow_up_payload = {
- "api_key": "675b900991ad2491c69389ca",
- "entry_id": "682eea70f81d67dc6c95a7a9",
- "is_start_workflow": "true",
- "data_list": all_data,
- "transaction_id": UUid
- }
+ except:
+ pass
+ break
+ routine_follow_up_payload = {
+ "api_key": "675b900991ad2491c69389ca",
+ "entry_id": "682eea70f81d67dc6c95a7a9",
+ "is_start_workflow": "true",
+ "data_list": all_data,
+ "transaction_id": UUid
+ }
- # print(routine_follow_up_payload)
- # 获取id
- payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "682eea70f81d67dc6c95a7a9"}
- get_ids = api_instance.entry_data_list(payload).get("data", [])
- delete_ids = [id["_id"] for id in get_ids]
-
- payload ={"api_key":"675b900991ad2491c69389ca","entry_id":"682eea70f81d67dc6c95a7a9",
- "data_ids":delete_ids,
- }
- api_instance.entry_data_batch_delete(payload)
-
- res = api_instance.entry_data_batch_create(routine_follow_up_payload)
- logger.info(f"创建结果:{res}")
- common_module.send_task_status(task_start_time, "手动添加日常回访")
+ # print(routine_follow_up_payload)
+ # 获取id
+ payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "682eea70f81d67dc6c95a7a9"}
+ get_ids = api_instance.entry_data_list(payload).get("data", [])
+ delete_ids = [id["_id"] for id in get_ids]
+ payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "682eea70f81d67dc6c95a7a9",
+ "data_ids": delete_ids,
+ }
+ api_instance.entry_data_batch_delete(payload)
+ res = api_instance.entry_data_batch_create(routine_follow_up_payload)
+ logger.info(f"创建结果:{res}")
+ common_module.send_task_status(task_start_time, "手动添加日常回访")
+ logger.info("手动添加日常回访完成")
+ except Exception as e:
+ error_task_logger.error(f"手动添加日常回访异常:{e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访异常", str(e))
if __name__ == '__main__':
diff --git a/back_ground_module/revisit_new_services_180.py b/back_ground_module/revisit_new_services_180.py
index 901c6ed..a394139 100644
--- a/back_ground_module/revisit_new_services_180.py
+++ b/back_ground_module/revisit_new_services_180.py
@@ -249,603 +249,612 @@ class NewServicesRevisit:
def main(self):
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ try:
+ logger.info("开始执行任务")
+ global png_url, key, upload_key, feature_dict
+ self.load_all_data()
+ logger.info("加载数据完成")
+ self.date_list = common_module.get_holiday_list()
+ self.data_NGV_S = common_module.get_ngv_details(days_back=1).astype(str) # 获取data_NGV 并转为str
+ self.date_one = self.calculate_date_one(start_offset=0)
+ self.index = self.build_index(self.json_list)
+ self.saas_create_time_180 = 173 # 新签日期
+ self.saas_create_time_90 = 83 # 新签日期
- global png_url, key, upload_key
- self.load_all_data()
+ for i in range(0, self.date_one): # 从NGV总表过滤
+ # now_time = datetime.datetime.now() + datetime.timedelta(days=-76)
+ # now_time = now_time + datetime.timedelta(days=-i)
+ now_time = datetime.datetime.now() + datetime.timedelta(days=-i)
+ today = now_time + datetime.timedelta(days=-self.saas_create_time_180)
+ formatted_today_180 = today.strftime("%Y-%m-%d")
+ today = now_time + datetime.timedelta(days=-self.saas_create_time_90)
+ formatted_today_90 = today.strftime("%Y-%m-%d")
+ logger.info(f"开始处理{formatted_today_180}与{formatted_today_90}的数据")
- self.date_list = common_module.get_holiday_list()
- self.data_NGV_S = common_module.get_ngv_details(days_back=1).astype(str) # 获取data_NGV 并转为str
- self.date_one = self.calculate_date_one(start_offset=0)
- self.index = self.build_index(self.json_list)
- self.saas_create_time_180 = 173 # 新签日期
- self.saas_create_time_90 = 83 # 新签日期
+ data_NGV = self.data_NGV_S.copy()
- print("开始运行main")
- print(self.date_one)
- for i in range(0, self.date_one): # 从NGV总表过滤
- # now_time = datetime.datetime.now() + datetime.timedelta(days=-76)
- # now_time = now_time + datetime.timedelta(days=-i)
- now_time = datetime.datetime.now() + datetime.timedelta(days=-i)
- today = now_time + datetime.timedelta(days=-self.saas_create_time_180)
- formatted_today_180 = today.strftime("%Y-%m-%d")
- today = now_time + datetime.timedelta(days=-self.saas_create_time_90)
- formatted_today_90 = today.strftime("%Y-%m-%d")
- print("SaaS开户回访日期:", formatted_today_180, formatted_today_90)
+ def replace_values(series):
+ # 使用条件判断来进行替换
+ return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
- data_NGV = self.data_NGV_S.copy()
+ # 对整个DataFrame的所有列应用替换函数
+ data_NGV = data_NGV.apply(replace_values)
+ # data_NGV.to_csv("dayinNGV.csv")
- def replace_values(series):
- # 使用条件判断来进行替换
- return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
+ # 定义优先级顺序
+ edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
+ customer_type_order = ["F", "E", "D", "C", "B", "A"] # 索引越小优先级越高
+ group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']
- # 对整个DataFrame的所有列应用替换函数
- data_NGV = data_NGV.apply(replace_values)
- # data_NGV.to_csv("dayinNGV.csv")
+ # 创建映射字典,并为不在列表中的值设置默认值
+ edition_map = {edition: idx for idx, edition in enumerate(edition_order)}
+ customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}
+ group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}
- # 定义优先级顺序
- edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
- customer_type_order = ["F", "E", "D", "C", "B", "A"] # 索引越小优先级越高
- group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']
+ # 添加用于排序的新列,并处理不在映射字典中的值
+ data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(
+ int) # 缺失值用最高优先级填充
+ data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(int)
+ data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)
+ # data_NGV.to_csv("88855.csv")
- # 创建映射字典,并为不在列表中的值设置默认值
- edition_map = {edition: idx for idx, edition in enumerate(edition_order)}
- customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}
- group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}
+ # 找到每组中 edition_rank 最小值对应的行
+ best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()
+ best_edition_rows = data_NGV.loc[best_edition_idx]
+ best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']
- # 添加用于排序的新列,并处理不在映射字典中的值
- data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(
- int) # 缺失值用最高优先级填充
- data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(int)
- data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)
- # data_NGV.to_csv("88855.csv")
+ # 找到每组中 customer_type_rank 最小值对应的行
+ best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()
+ best_customer_type_rows = data_NGV.loc[best_customer_type_idx]
+ best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(
+ lambda x: customer_type_order[x])
- # 找到每组中 edition_rank 最小值对应的行
- best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()
- best_edition_rows = data_NGV.loc[best_edition_idx]
- best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']
+ # 找到每组中 group_grade_rank 最小值对应的行
+ best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()
+ best_group_grade_rows = data_NGV.loc[best_group_grade_idx]
+ best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']
- # 找到每组中 customer_type_rank 最小值对应的行
- best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()
- best_customer_type_rows = data_NGV.loc[best_customer_type_idx]
- best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(
- lambda x: customer_type_order[x])
+ # 合并最佳值回到原数据集
+ best_values = (
+ best_edition_rows[['id_own_group', 'max_saas_edition']]
+ .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group',
+ how='outer')
+ .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')
+ )
- # 找到每组中 group_grade_rank 最小值对应的行
- best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()
- best_group_grade_rows = data_NGV.loc[best_group_grade_idx]
- best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']
+ # 将最佳值合并回原数据集
+ data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
- # 合并最佳值回到原数据集
- best_values = (
- best_edition_rows[['id_own_group', 'max_saas_edition']]
- .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group',
- how='outer')
- .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')
- )
+ condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件
- # 将最佳值合并回原数据集
- data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
+ ngvv2 = data_NGV[condition]
+ # ngvv2.to_excel(r"C:\Users\Administrator.DESKTOP-7IC2USJ\Desktop\NGVV2.xlsx")
- condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件
+ data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中
+ data_NGV_V2['条件'] = (data_NGV_V2['org_type'] == "一般") & (data_NGV_V2['org_status'] == '留存') & (
+ data_NGV_V2['area_manager'] != '殷昊') & (
+ data_NGV_V2['area_manager'] != '孙玉蕾') & (
+ data_NGV_V2['is_main_org'] != 1)
+ data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2["条件"]]
+ # 步骤4: 过滤存在的记录
+ data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])
+ filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]
- ngvv2 = data_NGV[condition]
- # ngvv2.to_excel(r"C:\Users\Administrator.DESKTOP-7IC2USJ\Desktop\NGVV2.xlsx")
+ fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
+ # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))
- data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中
- data_NGV_V2['条件'] = (data_NGV_V2['org_type'] == "一般") & (data_NGV_V2['org_status'] == '留存') & (
- data_NGV_V2['area_manager'] != '殷昊') & (
- data_NGV_V2['area_manager'] != '孙玉蕾') & (
- data_NGV_V2['is_main_org'] != 1)
- data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2["条件"]]
- # 步骤4: 过滤存在的记录
- data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])
- filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]
+ fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}
+ filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)
+ filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)
- fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
- # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))
+ result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')
- fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}
- filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)
- filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)
+ data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
+ data_NGV['area_manager'] != '殷昊') & (
+ data_NGV['area_manager'] != '孙玉蕾') & (
+ (data_NGV['saas_create_time'] == formatted_today_180) | (
+ data_NGV['saas_create_time'] == formatted_today_90)) & (
+ data_NGV['is_main_org'] == "1")
- result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')
+ data_NGV = data_NGV.loc[data_NGV["条件"]]
- data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
- data_NGV['area_manager'] != '殷昊') & (
- data_NGV['area_manager'] != '孙玉蕾') & (
- (data_NGV['saas_create_time'] == formatted_today_180) | (
- data_NGV['saas_create_time'] == formatted_today_90)) & (
- data_NGV['is_main_org'] == "1")
-
- data_NGV = data_NGV.loc[data_NGV["条件"]]
-
- data_NGV = pd.concat([data_NGV, result], axis=0)
- print(len(data_NGV), "20250325")
-
- # 定义一个函数,根据 saas_create_time 字段的值设置阶段列和主要目的列的值
- def set_columns(row):
- if row['saas_create_time'] == formatted_today_180:
- row['跟进阶段'] = '新签后180天'
- row['主要目的'] = '关怀使用情况,邀约转介绍,跟进增购商机,识别首年续约风险,及时跟进提报。'
- elif row['saas_create_time'] == formatted_today_90:
- row['跟进阶段'] = '新签后90天'
- row['主要目的'] = '关怀使用情况,解答使用问题,强化培训,挖掘增购商机。'
- else:
- row['跟进阶段'] = "派发异常请联系数据组!" # 返回其他默认值
- row['主要目的'] = "派发异常请联系数据组!" # 返回其他默认值
- return row
-
- # 使用 apply 方法将函数应用到每一行
- data_NGV = data_NGV.apply(set_columns, axis=1)
-
- print("SaaS开户回访人数:", len(data_NGV))
- print(data_NGV)
-
- # 重置索引
- data_NGV = data_NGV.reset_index(drop=True)
-
- for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
- try:
- # print(row["org_code"]) # 数据验证
- # print(row["service_impl_principal"])
- # print(row["area_manager"])
- # print(row["technician"])
- payload_dict = {}
- saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
-
-
-
- NGV_roles = {
- 'relationship_manager': row['service_impl_principal'], # 运营负责人
- # 'relationship_manager': "张阳", # 运营负责人
- 'area_manager': row['area_manager'], # 区域经理
- 'technician': row['technician'], # 技术专家
- 'salesmen': row['salesmen'], # 销售负责人
- }
-
- for role, name in NGV_roles.items(): # 寻找对应的员工ID
- for row_item in self.staff_id_list:
- staff_id = self.get_staff_id(row_item, name)
- if staff_id:
- NGV_roles[role] = staff_id
- break # 找到后退出循环
- else:
- NGV_roles[role] = None # 如果没有找到对应的员工ID
-
- # 回访人员: 需确认 四年以下 technician
- if int(saas_use_year) < 4:
-
- relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
- ['relationship_manager',
- 'area_manager',
- 'technician', 'salesmen']]
-
- # 如果未找到运营负责人,则根据省市区派发给日常回访客服
- if not relationship_manager:
- relationship_manager = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )[0]
- if not technician:
- technician = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )[2]
-
- if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
- payload_dict.update({
- "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
- })
- else:
- payload_dict.update({
- "_widget_1734590278288": {"value": technician}, # 跟进人是技术专家
- })
+ data_NGV = pd.concat([data_NGV, result], axis=0)
+ logger.info(f"NGV过滤后长度:{len(data_NGV)}")
+ # 定义一个函数,根据 saas_create_time 字段的值设置阶段列和主要目的列的值
+ def set_columns(row):
+ if row['saas_create_time'] == formatted_today_180:
+ row['跟进阶段'] = '新签后180天'
+ row['主要目的'] = '关怀使用情况,邀约转介绍,跟进增购商机,识别首年续约风险,及时跟进提报。'
+ elif row['saas_create_time'] == formatted_today_90:
+ row['跟进阶段'] = '新签后90天'
+ row['主要目的'] = '关怀使用情况,解答使用问题,强化培训,挖掘增购商机。'
else:
- salesmen = [NGV_roles[role] for role in
- ['salesmen']]
- # 直接根据省市区派发给日常回访客服
- relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )
+ row['跟进阶段'] = "派发异常请联系数据组!" # 返回其他默认值
+ row['主要目的'] = "派发异常请联系数据组!" # 返回其他默认值
+ return row
+
+ # 使用 apply 方法将函数应用到每一行
+ data_NGV = data_NGV.apply(set_columns, axis=1)
+
+ logger.info(f"SaaS开户回访人数:{len(data_NGV)}")
+
+ # 重置索引
+ data_NGV = data_NGV.reset_index(drop=True)
+
+ for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
+ try:
+ # print(row["org_code"]) # 数据验证
+ # print(row["service_impl_principal"])
+ # print(row["area_manager"])
+ # print(row["technician"])
+ payload_dict = {}
+ saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
+
+
+
+ NGV_roles = {
+ 'relationship_manager': row['service_impl_principal'], # 运营负责人
+ # 'relationship_manager': "张阳", # 运营负责人
+ 'area_manager': row['area_manager'], # 区域经理
+ 'technician': row['technician'], # 技术专家
+ 'salesmen': row['salesmen'], # 销售负责人
+ }
+
+ for role, name in NGV_roles.items(): # 寻找对应的员工ID
+ for row_item in self.staff_id_list:
+ staff_id = self.get_staff_id(row_item, name)
+ if staff_id:
+ NGV_roles[role] = staff_id
+ break # 找到后退出循环
+ else:
+ NGV_roles[role] = None # 如果没有找到对应的员工ID
+
+ # 回访人员: 需确认 四年以下 technician
+ if int(saas_use_year) < 4:
+
+ relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
+ ['relationship_manager',
+ 'area_manager',
+ 'technician', 'salesmen']]
+
+ # 如果未找到运营负责人,则根据省市区派发给日常回访客服
+ if not relationship_manager:
+ relationship_manager = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
+ )[0]
+ if not technician:
+ technician = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
+ )[2]
+
+ if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
+ payload_dict.update({
+ "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
+ })
+ else:
+ payload_dict.update({
+ "_widget_1734590278288": {"value": technician}, # 跟进人是技术专家
+ })
- if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
- payload_dict.update({
- "_widget_1734590278288": {"value": customer_service} # 跟进人是日常回访客服
- })
else:
- payload_dict.update({
- "_widget_1734590278288": {"value": technician} # 跟进人是技术专家
- })
-
- payload_dict.update({
- # "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
- "_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
- "_widget_1734590278290": {"value": area_manager}, # 区域经理
- "_widget_1734590278291": {"value": technician}, # 技术专家
- "_widget_1735290738545": {"value": salesmen} # 销售负责人
- })
-
- if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
- payload_dict.update({
- "_widget_1734590278288": {"value": "051612246035720178"}, # 跟进人是赵柄诚
- })
-
- # 输出结果
- print("SaaS开户回访人员:", relationship_manager or "未分配")
- print("SaaS技术专家:", technician or "未分配")
- print("SaaS区域经理:", area_manager or "未分配")
-
- # 判断权限唯一值
- # pattern = r'([\u4e00-\u9fa5]+)\('
- # match = re.search(pattern, row['max_group_grade'])
- # group_grade = match.group(1)
- group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
-
- if not row['saas_customer_type'] or row['saas_customer_type'] == 'NA' or row[
- 'saas_customer_type'] == 'None':
- row['saas_customer_type'] = "F"
-
- NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
- print("权限唯一值:", NGV_store_level_key)
-
- Billing = None
- for item in self.permissions_table:
- if NGV_store_level_key == item.get("_widget_1734056507963"): # 合并(等级-类型-分层)
- print("该门店开单的权限是:", item.get(item.get("_widget_1734055617039")))
- Billing = item.get("_widget_1734055617039") # 开单
- Service_Alerts = item.get("_widget_1734055617040") # 服务提醒
- membership = item.get("_widget_1734055617041") # 会员卡
- SMS = item.get("_widget_1734055617042") # 短信
- Public_domain_applets = item.get("_widget_1734055617043") # 公域小程序
- Private_domain_applets = item.get("_widget_1734055617044") # 私域小程序
- Test_sheet = item.get("_widget_1734055617045") # 检测单
- AI_poster = item.get("_widget_1734055617046") # AI海报
- Business_wallets = item.get("_widget_1734055617047") # 企业钱包
- Precision_marketing = item.get("_widget_1734055617049") # 精准营销
- Paid_memberships = item.get("_widget_1734055617051") # 付费会员
- business_WeCom = item.get("_widget_1734055617052") # 企业微信
- Insurance_policy_identification = item.get("_widget_1734055617053") # 保险单识别
- Insurance_bots = item.get("_widget_1734055617054") # 保险机器人
- Camera_pick_up = item.get("_widget_1734055617055") # 摄像头接车
- Camera_billing = item.get("_widget_1734055617056") # 摄像头开单
- Transparent_workshop = item.get("_widget_1734055617057") # 透明车间
- Cross_industry_cooperation = item.get("_widget_1734055617058") # 异业合作
- BI_Insights = item.get("_widget_1734055617059") # BI洞察
-
- payload_dict.update(
- {
- "_widget_1734073342350": {"value": Billing},
- "_widget_1735004315757": {"value": Service_Alerts},
- "_widget_1735004315756": {"value": membership},
- "_widget_1735004315755": {"value": SMS},
- "_widget_1735004315754": {"value": Public_domain_applets},
- "_widget_1735004315753": {"value": Private_domain_applets},
- "_widget_1735004315752": {"value": Test_sheet},
- "_widget_1735004315751": {"value": AI_poster},
- "_widget_1735004315750": {"value": Business_wallets},
- "_widget_1735004315749": {"value": Precision_marketing},
- "_widget_1735004315748": {"value": Paid_memberships},
- "_widget_1735004315747": {"value": business_WeCom},
- "_widget_1735004315746": {"value": Insurance_policy_identification},
- "_widget_1735004315745": {"value": Insurance_bots},
- "_widget_1735004315744": {"value": Camera_pick_up},
- "_widget_1735004315743": {"value": Camera_billing},
- "_widget_1735004315742": {"value": Transparent_workshop},
- "_widget_1735004315741": {"value": Cross_industry_cooperation},
- "_widget_1734073342352": {"value": BI_Insights},
-
- }
+ salesmen = [NGV_roles[role] for role in
+ ['salesmen']]
+ # 直接根据省市区派发给日常回访客服
+ relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
)
- feature_dict = {
- "开单": "_widget_1734073342350",
- "服务提醒": "_widget_1735004315757",
- "会员卡": "_widget_1735004315756",
- "短信": "_widget_1735004315755",
- "公域小程序": "_widget_1735004315754",
- "私域小程序": "_widget_1735004315753",
- "检测单": "_widget_1735004315752",
- "AI海报": "_widget_1735004315751",
- "企业钱包": "_widget_1735004315750",
- "精准营销": "_widget_1735004315749",
- "付费会员": "_widget_1735004315748",
- "企业微信": "_widget_1735004315747",
- "保险单识别": "_widget_1735004315746",
- "保险机器人": "_widget_1735004315745",
- "摄像头接车": "_widget_1735004315744",
- "摄像头开单": "_widget_1735004315743",
- "透明车间": "_widget_1735004315742",
- "异业合作": "_widget_1735004315741",
- "BI洞察": "_widget_1734073342352",
+ if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
+ payload_dict.update({
+ "_widget_1734590278288": {"value": customer_service} # 跟进人是日常回访客服
+ })
+ else:
+ payload_dict.update({
+ "_widget_1734590278288": {"value": technician} # 跟进人是技术专家
+ })
- }
- # _widget_1735527329557 下次是否推荐
- for new_item in self.get_feature_usage:
- for feature_module, feature_value in feature_dict.items(): # 模块
- if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
- "_widget_1735527329557") == "否" and new_item.get(
- "_widget_1735280720550") == \
- row["id_own_org"]: # 下次是否推荐 功能使用情况表
- print(f"{feature_value}进行了更改")
- payload_dict.update({f"{feature_value}": {"value": "×"}})
+ payload_dict.update({
+ # "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
+ "_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
+ "_widget_1734590278290": {"value": area_manager}, # 区域经理
+ "_widget_1734590278291": {"value": technician}, # 技术专家
+ "_widget_1735290738545": {"value": salesmen} # 销售负责人
+ })
- if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
- "_widget_1736414617462") == "否" and new_item.get(
- "_widget_1735280720550") == \
- row["id_own_org"]: # 下次是否跟进
- print(f"{feature_value}进行了更改")
- payload_dict.update({f"{feature_value}": {"value": "×"}})
+ if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
+ payload_dict.update({
+ "_widget_1734590278288": {"value": "051612246035720178"}, # 跟进人是赵柄诚
+ })
- fields_to_check = {
- "_widget_1735004315763": Billing, # 开单
- "_widget_1735106258016": Service_Alerts, # 服务提醒
- "_widget_1735106258036": membership, # 会员卡
- "_widget_1735106258086": SMS, # 短信
- "_widget_1735106258112": Public_domain_applets, # 公域小程序
- "_widget_1735106258141": Private_domain_applets, # 私域小程序
- "_widget_1735107354648": Test_sheet, # 检测单
- "_widget_1735107354725": AI_poster, # AI海报
- "_widget_1735107354811": Business_wallets, # 企业钱包
- "_widget_1735107354906": Precision_marketing, # 精准营销
- "_widget_1735107354980": Paid_memberships, # 付费会员
- "_widget_1735107355093": business_WeCom, # 企业微信
- "_widget_1735107355143": Insurance_policy_identification, # 保险单识别
- "_widget_1735107355235": Insurance_bots, # 保险机器人
- "_widget_1735107355333": Camera_pick_up, # 摄像头接车
- "_widget_1735107355392": Camera_billing, # 摄像头开单
- "_widget_1735107355502": Transparent_workshop, # 透明车间
- "_widget_1735107355618": Cross_industry_cooperation, # 异业合作
- "_widget_1735107355740": BI_Insights # BI洞察
- }
+ # 输出结果
+ logger.info(f"SaaS开户回访人员:{relationship_manager}")
+ logger.info(f"SaaS技术专家:{technician}")
+ logger.info(f"SaaS区域经理:{area_manager}")
- # 遍历每个字段,检查其值并更新payload_dict
- for widget_id, field_name in fields_to_check.items():
- if field_name == "√":
- payload_dict.update({widget_id: {"value": "是"}})
+ # 判断权限唯一值
+ # pattern = r'([\u4e00-\u9fa5]+)\('
+ # match = re.search(pattern, row['max_group_grade'])
+ # group_grade = match.group(1)
+ group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
- break
+ if not row['saas_customer_type'] or row['saas_customer_type'] == 'NA' or row[
+ 'saas_customer_type'] == 'None':
+ row['saas_customer_type'] = "F"
- is_continue = False
- # 如果门店倒闭则不派发
- for store in self.NGV_data_list:
- if row["id_own_org"] == store.get("_widget_1734062123069") and store.get(
- "_widget_1752027386523") == "门店倒闭":
- is_continue = True
- print(f"门店已关闭,不派发")
- break
- if is_continue:
- continue
+ NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
+ logger.info(f"权限唯一值:{NGV_store_level_key}")
- if not Billing:
- print(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
+ Billing = None
+ for item in self.permissions_table:
+ if NGV_store_level_key == item.get("_widget_1734056507963"): # 合并(等级-类型-分层)
+ print("该门店开单的权限是:", item.get(item.get("_widget_1734055617039")))
+ Billing = item.get("_widget_1734055617039") # 开单
+ Service_Alerts = item.get("_widget_1734055617040") # 服务提醒
+ membership = item.get("_widget_1734055617041") # 会员卡
+ SMS = item.get("_widget_1734055617042") # 短信
+ Public_domain_applets = item.get("_widget_1734055617043") # 公域小程序
+ Private_domain_applets = item.get("_widget_1734055617044") # 私域小程序
+ Test_sheet = item.get("_widget_1734055617045") # 检测单
+ AI_poster = item.get("_widget_1734055617046") # AI海报
+ Business_wallets = item.get("_widget_1734055617047") # 企业钱包
+ Precision_marketing = item.get("_widget_1734055617049") # 精准营销
+ Paid_memberships = item.get("_widget_1734055617051") # 付费会员
+ business_WeCom = item.get("_widget_1734055617052") # 企业微信
+ Insurance_policy_identification = item.get("_widget_1734055617053") # 保险单识别
+ Insurance_bots = item.get("_widget_1734055617054") # 保险机器人
+ Camera_pick_up = item.get("_widget_1734055617055") # 摄像头接车
+ Camera_billing = item.get("_widget_1734055617056") # 摄像头开单
+ Transparent_workshop = item.get("_widget_1734055617057") # 透明车间
+ Cross_industry_cooperation = item.get("_widget_1734055617058") # 异业合作
+ BI_Insights = item.get("_widget_1734055617059") # BI洞察
- if row["active_status_fmt"] == "活跃": # 开单 是否使用
- payload_dict.update({"_widget_1735004315765": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735004315765": {"value": "否"}})
- try:
- if row["saas_edition_fmt"] not in ["基础版", "入门版"]: # 会员卡 是否拥有
- payload_dict.update({"_widget_1735106258036": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735106258036": {"value": "否"}})
- except Exception as e:
- print(f"会员卡识别:Error finding customer service: {e}")
- try:
- if row["card_bill_day_count_last_30_day"] != "0": # 会员卡 是否使用
- payload_dict.update({"_widget_1735106258038": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735106258038": {"value": "否"}})
- except Exception as e:
- print(f"会员卡识别:Error finding customer service: {e}")
- # print(self.service_remind.get("_widget_1735112637045"))
- payload_dict["_widget_1735106258018"] = {"value": "否"}
+ payload_dict.update(
+ {
+ "_widget_1734073342350": {"value": Billing},
+ "_widget_1735004315757": {"value": Service_Alerts},
+ "_widget_1735004315756": {"value": membership},
+ "_widget_1735004315755": {"value": SMS},
+ "_widget_1735004315754": {"value": Public_domain_applets},
+ "_widget_1735004315753": {"value": Private_domain_applets},
+ "_widget_1735004315752": {"value": Test_sheet},
+ "_widget_1735004315751": {"value": AI_poster},
+ "_widget_1735004315750": {"value": Business_wallets},
+ "_widget_1735004315749": {"value": Precision_marketing},
+ "_widget_1735004315748": {"value": Paid_memberships},
+ "_widget_1735004315747": {"value": business_WeCom},
+ "_widget_1735004315746": {"value": Insurance_policy_identification},
+ "_widget_1735004315745": {"value": Insurance_bots},
+ "_widget_1735004315744": {"value": Camera_pick_up},
+ "_widget_1735004315743": {"value": Camera_billing},
+ "_widget_1735004315742": {"value": Transparent_workshop},
+ "_widget_1735004315741": {"value": Cross_industry_cooperation},
+ "_widget_1734073342352": {"value": BI_Insights},
+
+ }
+ )
+
+ feature_dict = {
+ "开单": "_widget_1734073342350",
+ "服务提醒": "_widget_1735004315757",
+ "会员卡": "_widget_1735004315756",
+ "短信": "_widget_1735004315755",
+ "公域小程序": "_widget_1735004315754",
+ "私域小程序": "_widget_1735004315753",
+ "检测单": "_widget_1735004315752",
+ "AI海报": "_widget_1735004315751",
+ "企业钱包": "_widget_1735004315750",
+ "精准营销": "_widget_1735004315749",
+ "付费会员": "_widget_1735004315748",
+ "企业微信": "_widget_1735004315747",
+ "保险单识别": "_widget_1735004315746",
+ "保险机器人": "_widget_1735004315745",
+ "摄像头接车": "_widget_1735004315744",
+ "摄像头开单": "_widget_1735004315743",
+ "透明车间": "_widget_1735004315742",
+ "异业合作": "_widget_1735004315741",
+ "BI洞察": "_widget_1734073342352",
+
+ }
+ # _widget_1735527329557 下次是否推荐
+ for new_item in self.get_feature_usage:
+ for feature_module, feature_value in feature_dict.items(): # 模块
+ if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
+ "_widget_1735527329557") == "否" and new_item.get(
+ "_widget_1735280720550") == \
+ row["id_own_org"]: # 下次是否推荐 功能使用情况表
+ logger.info(f"{feature_value}进行了更改")
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+
+ if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
+ "_widget_1736414617462") == "否" and new_item.get(
+ "_widget_1735280720550") == \
+ row["id_own_org"]: # 下次是否跟进
+ logger.info(f"{feature_value}进行了更改")
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+
+ fields_to_check = {
+ "_widget_1735004315763": Billing, # 开单
+ "_widget_1735106258016": Service_Alerts, # 服务提醒
+ "_widget_1735106258036": membership, # 会员卡
+ "_widget_1735106258086": SMS, # 短信
+ "_widget_1735106258112": Public_domain_applets, # 公域小程序
+ "_widget_1735106258141": Private_domain_applets, # 私域小程序
+ "_widget_1735107354648": Test_sheet, # 检测单
+ "_widget_1735107354725": AI_poster, # AI海报
+ "_widget_1735107354811": Business_wallets, # 企业钱包
+ "_widget_1735107354906": Precision_marketing, # 精准营销
+ "_widget_1735107354980": Paid_memberships, # 付费会员
+ "_widget_1735107355093": business_WeCom, # 企业微信
+ "_widget_1735107355143": Insurance_policy_identification, # 保险单识别
+ "_widget_1735107355235": Insurance_bots, # 保险机器人
+ "_widget_1735107355333": Camera_pick_up, # 摄像头接车
+ "_widget_1735107355392": Camera_billing, # 摄像头开单
+ "_widget_1735107355502": Transparent_workshop, # 透明车间
+ "_widget_1735107355618": Cross_industry_cooperation, # 异业合作
+ "_widget_1735107355740": BI_Insights # BI洞察
+ }
+
+ # 遍历每个字段,检查其值并更新payload_dict
+ for widget_id, field_name in fields_to_check.items():
+ if field_name == "√":
+ payload_dict.update({widget_id: {"value": "是"}})
- for item in self.service_remind:
- if row["id_own_group"] == item.get("_widget_1735112637043"):
- if int(item.get("_widget_1735112637045")) < 180 and int(
- item.get("_widget_1735112637046")) == 1: # 服务提醒 是否使用
- payload_dict.update({"_widget_1735106258018": {"value": "是"}})
- break
- elif int(item.get("_widget_1735112637048")) > 0:
- payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- keys_to_check = [
- "_widget_1735113110155"
- ] # 智能检测 是否使用
+ is_continue = False
+ # 如果门店倒闭则不派发
+ for store in self.NGV_data_list:
+ if row["id_own_org"] == store.get("_widget_1734062123069") and store.get(
+ "_widget_1752027386523") == "门店倒闭":
+ is_continue = True
+ print(f"门店已关闭,不派发")
+ break
+ if is_continue:
+ continue
- # 初始化默认值为"否"
- payload_dict["_widget_1735107354650"] = {"value": "否"}
+ if not Billing:
+ logger.warning(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
- # 检查每个键,如果有一个大于0,则更新为"是"并停止检查
- for key in keys_to_check:
- for item in self.Smart_detection:
- if row["id_own_org"] == item.get("_widget_1735113110147"):
- if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况
- payload_dict["_widget_1735107354650"]["value"] = "是"
- break
-
- # 近30天业务单量=0 则其它所有模块均不推荐
- try:
- for feature_module, feature_value in feature_dict.items(): # 模块
- if row["bill_count_last_30_day"] == '0' and payload_dict[feature_value]["value"] == '△':
- payload_dict.update({f"{feature_value}": {"value": "×"}})
- except Exception as e:
- print(f"不开单识别:Error finding customer service: {e}")
- # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐
- try:
- if row["org_code"] in self.widget_list:
- payload_dict.update({'_widget_1735004315746': {"value": "△"}})
- except Exception as e:
- print(f"保单识别:Error finding customer service: {e}")
- # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
- try:
- for item in self.private_domain:
- if row["id_own_group"] == item.get("_widget_1742795002375"): # 公司id
- if int(item.get("_widget_1742795002379")) > 0: # 上架商品数
- payload_dict.update({"_widget_1735106258143": {"value": "是"}}) # DX:是否拥有
- break
- else:
- payload_dict.update({"_widget_1735106258143": {"value": "否"}}) # DX:是否拥有
- break
- except Exception as e:
- print(f"私域小程序:Error finding customer service: {e}")
- try:
- high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']
- if row["saas_edition_fmt"] in high_version:
- payload_dict.update({'_widget_1735106258141': {"value": "是"}}) # SYXCX:是否拥有
+ if row["active_status_fmt"] == "活跃": # 开单 是否使用
+ payload_dict.update({"_widget_1735004315765": {"value": "是"}})
else:
- payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
- except Exception as e:
- print(f"私域小程序:Error finding customer service: {e}")
+ payload_dict.update({"_widget_1735004315765": {"value": "否"}})
+ try:
+ if row["saas_edition_fmt"] not in ["基础版", "入门版"]: # 会员卡 是否拥有
+ payload_dict.update({"_widget_1735106258036": {"value": "是"}})
+ else:
+ payload_dict.update({"_widget_1735106258036": {"value": "否"}})
+ except Exception as e:
+ error_task_logger.error(f"会员卡拥有识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-会员卡拥有识别", str(e))
+ try:
+ if row["card_bill_day_count_last_30_day"] != "0": # 会员卡 是否使用
+ payload_dict.update({"_widget_1735106258038": {"value": "是"}})
+ else:
+ payload_dict.update({"_widget_1735106258038": {"value": "否"}})
+ except Exception as e:
+ error_task_logger.error(f"会员卡使用识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-会员卡使用识别", str(e))
+ # print(self.service_remind.get("_widget_1735112637045"))
+ payload_dict["_widget_1735106258018"] = {"value": "否"}
- # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
- try:
- for item in self.public_domain:
- if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
- if int(item.get("_widget_1742784257509")) == 1: # 发布商品数量
- payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
+ for item in self.service_remind:
+ if row["id_own_group"] == item.get("_widget_1735112637043"):
+ if int(item.get("_widget_1735112637045")) < 180 and int(
+ item.get("_widget_1735112637046")) == 1: # 服务提醒 是否使用
+ payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- else:
- payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
+ elif int(item.get("_widget_1735112637048")) > 0:
+ payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- except Exception as e:
- print(f"公域小程序:Error finding customer service: {e}")
- try:
- if row["id_own_org"] in self.public_domain_list:
- payload_dict.update({'_widget_1735106258112': {"value": "是"}}) # GYXCX:是否拥有
- else:
- payload_dict.update({'_widget_1735106258112': {"value": "否"}}) # GYXCX:是否拥有
- except Exception as e:
- print(f"公域小程序:Error finding customer service: {e}")
- # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字
- try:
- if row["id_own_org"] in self.different_industries_list:
- payload_dict.update({'_widget_1735107355618': {"value": "是"}}) # YYHZ:是否拥有
- else:
- payload_dict.update({'_widget_1735107355618': {"value": "否"}}) # YYHZ:是否拥有
- except Exception as e:
- print(f"异业合作:Error finding customer service: {e}")
- # 短信:根据是否启动短信功能判断是否拥有,根据
- try:
- for item in self.groupnotification:
- if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
- if int(item.get("_widget_1743065201886")) == 1: # 是否启动短信功能
- payload_dict.update({"_widget_1735106258086": {"value": "是"}}) # DX:是否拥有
- break
- else:
- payload_dict.update({"_widget_1735106258086": {"value": "否"}}) # DX:是否拥有
- break
- except Exception as e:
- print(f"短信:Error finding customer service: {e}")
+ keys_to_check = [
+ "_widget_1735113110155"
+ ] # 智能检测 是否使用
- try:
- for item in self.groupnotification:
- if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
- if int(item.get("_widget_1743065201889")) > 0: # 累计发送成功总人数
- payload_dict.update({"_widget_1735106258088": {"value": "是"}}) # DX:是否使用
- break
- else:
- payload_dict.update({"_widget_1735106258088": {"value": "否"}}) # DX:是否使用
- break
- except Exception as e:
- print(f"短信:Error finding customer service: {e}")
+ # 初始化默认值为"否"
+ payload_dict["_widget_1735107354650"] = {"value": "否"}
- NGV_data_id = None
- # 获取关联数据
- for NGV_Data in self.NGV_data_list:
- # NGV_Data = NGV_Data.get("data")
- if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
- NGV_data_id = NGV_Data.get("_id")
- print(NGV_data_id)
- try:
- png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
- except:
- png_url = ""
- print(png_url)
- if not NGV_data_id:
- print("未找到数据ID")
+ # 检查每个键,如果有一个大于0,则更新为"是"并停止检查
+ for key in keys_to_check:
+ for item in self.Smart_detection:
+ if row["id_own_org"] == item.get("_widget_1735113110147"):
+ if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况
+ payload_dict["_widget_1735107354650"]["value"] = "是"
+ break
- distribution_date = datetime.datetime.now(datetime.timezone.utc)
- distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
+ # 近30天业务单量=0 则其它所有模块均不推荐
+ try:
+ for feature_module, feature_value in feature_dict.items(): # 模块
+ if row["bill_count_last_30_day"] == '0' and payload_dict[feature_value]["value"] == '△':
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+ except Exception as e:
+ error_task_logger.error(f"不开单识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-不开单识别", str(e))
+ # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐
+ try:
+ if row["org_code"] in self.widget_list:
+ payload_dict.update({'_widget_1735004315746': {"value": "△"}})
+ except Exception as e:
+ error_task_logger.error(f"保单识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-保单识别", str(e))
+ # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
+ try:
+ for item in self.private_domain:
+ if row["id_own_group"] == item.get("_widget_1742795002375"): # 公司id
+ if int(item.get("_widget_1742795002379")) > 0: # 上架商品数
+ payload_dict.update({"_widget_1735106258143": {"value": "是"}}) # DX:是否拥有
+ break
+ else:
+ payload_dict.update({"_widget_1735106258143": {"value": "否"}}) # DX:是否拥有
+ break
+ except Exception as e:
+ error_task_logger.error(f"小程序识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-小程序识别", str(e))
+ try:
+ high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']
+ if row["saas_edition_fmt"] in high_version:
+ payload_dict.update({'_widget_1735106258141': {"value": "是"}}) # SYXCX:是否拥有
+ else:
+ payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"私域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-私域小程序", str(e))
- upload_key = None
- UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
- if png_url:
- save_dir = "sampleCloud" # 设置输出目录
+ # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
+ try:
+ for item in self.public_domain:
+ if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
+ if int(item.get("_widget_1742784257509")) == 1: # 发布商品数量
+ payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
+ break
+ else:
+ payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
+ break
+ except Exception as e:
+ error_task_logger.error(f"公域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-公域小程序", str(e))
- # 创建输出目录(如果不存在)
- import os
+ try:
+ if row["id_own_org"] in self.public_domain_list:
+ payload_dict.update({'_widget_1735106258112': {"value": "是"}}) # GYXCX:是否拥有
+ else:
+ payload_dict.update({'_widget_1735106258112': {"value": "否"}}) # GYXCX:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"公域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-公域小程序", str(e))
- os.makedirs(save_dir, exist_ok=True)
+ # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字
+ try:
+ if row["id_own_org"] in self.different_industries_list:
+ payload_dict.update({'_widget_1735107355618': {"value": "是"}}) # YYHZ:是否拥有
+ else:
+ payload_dict.update({'_widget_1735107355618': {"value": "否"}}) # YYHZ:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"异业合作:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-异业合作", str(e))
- save_path = fr'{save_dir}\png\{time.strftime("%Y%m%d%H%M%S", time.localtime())}.png'
+ # 短信:根据是否启动短信功能判断是否拥有,根据
+ try:
+ for item in self.groupnotification:
+ if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
+ if int(item.get("_widget_1743065201886")) == 1: # 是否启动短信功能
+ payload_dict.update({"_widget_1735106258086": {"value": "是"}}) # DX:是否拥有
+ break
+ else:
+ payload_dict.update({"_widget_1735106258086": {"value": "否"}}) # DX:是否拥有
+ break
+ except Exception as e:
+ error_task_logger.error(f"短信是否使用:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-短信是否使用", str(e))
- NewServicesRevisit.download_url_content(png_url, save_path)
+ try:
+ for item in self.groupnotification:
+ if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
+ if int(item.get("_widget_1743065201889")) > 0: # 累计发送成功总人数
+ payload_dict.update({"_widget_1735106258088": {"value": "是"}}) # DX:是否使用
+ break
+ else:
+ payload_dict.update({"_widget_1735106258088": {"value": "否"}}) # DX:是否使用
+ break
+ except Exception as e:
+ error_task_logger.error(f"短信是否使用:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-短信是否使用", str(e))
- up_data = api_instance.get_upload_token(
- {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b9c63925cd404038a6b86",
- "transaction_id": UUid})
+ NGV_data_id = None
+ # 获取关联数据
+ for NGV_Data in self.NGV_data_list:
+ # NGV_Data = NGV_Data.get("data")
+ if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
+ NGV_data_id = NGV_Data.get("_id")
+ logger.info(f"关联数据数据id:{NGV_data_id}")
+ try:
+ png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
+ except:
+ png_url = ""
+ logger.info(f"关联数据图片:{png_url}")
+ if not NGV_data_id:
+ logger.warning("未找到数据ID")
- upload_url = up_data.get("upload_url")
- upload_token = up_data.get("upload_token")
+ distribution_date = datetime.datetime.now(datetime.timezone.utc)
+ distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
- upload_result = api_instance.upload_file(
- {"upload_url": upload_url, "upload_token": upload_token, "file_path": save_path})
- upload_key = upload_result.get("key")
- # print("已上传文件")
- # print(upload_result)
+ upload_key = None
+ UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
+ if png_url:
+ save_dir = "sampleCloud" # 设置输出目录
- # print(upload_key)
+ # 创建输出目录(如果不存在)
+ import os
- payload_dict.update({
- "_widget_1734590278279": {"value": row["group_name"]}, # 公司名称
- "_widget_1735112931760": {"value": row["id_own_group"]}, # 公司id
- "_widget_1735112931761": {"value": row["id_own_org"]}, # 门店id
- "_widget_1734590278281": {"value": row['org_name']}, # 门店名称
- "_widget_1734590278292": {"value": row["跟进阶段"]}, # 跟进阶段
- "_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
- "_widget_1742548684369": {"value": row['主要目的']}, # 主要目的
- "_widget_1734590278266": {"value": row['region_name']}, # 大区
- "_widget_1734590278285": {"value": row['branch_name']}, # 小区
- "_widget_1734590278284": {"value": row['province_name']}, # 省
- "_widget_1734590278283": {"value": row['city_name']}, # 市
- "_widget_1734590278282": {"value": row['area_name']}, # 区
- "_widget_1734590278278": {"value": row['saas_customer_type']}, # 门店分层
- "_widget_1734590278277": {"value": row['group_grade']}, # 公司等级
- "_widget_1734590278276": {"value": row['limit_user_type']}, # 限制账户类型
- "_widget_1734590278275": {"value": row['active_user_type']}, # 有效账户类型
- "_widget_1734590278274": {"value": row['saas_version']}, # ERP操作模式
- "_widget_1734590278273": {"value": row['saas_use_year']}, # 使用时长
- "_widget_1734590278272": {"value": row['org_stage']}, # 门店阶段
- "_widget_1734590278271": {"value": row['manage_model']}, # 经营模式
- "_widget_1734590278267": {"value": row['contacts']}, # 联系人
- "_widget_1734590278287": {"value": row['contact_mobile']}, # 联系手机号
- "_widget_1734590278286": {"value": row['saas_edition_fmt']}, # SaaS版本
- "_widget_1734590278280": {"value": row['org_code']}, # 门店编码
- "_widget_1735096489244": {"value": distribution_date}, # 派发时间
- "_widget_1742895342914": {"value": row['business_scope_fmt']}, # 经营范围
- "_widget_1742895342915": {"value": row['station_number']}, # 工位数
- "_widget_1742895342916": {"value": [upload_key]} # 门头照片
- })
+ os.makedirs(save_dir, exist_ok=True)
- routine_follow_up_payload = {
- "api_key": "675b900991ad2491c69389ca",
- "entry_id": "675b9c63925cd404038a6b86",
- "is_start_workflow": "true",
- "data": payload_dict,
- "transaction_id": UUid
- }
+ save_path = fr'{save_dir}\png\{time.strftime("%Y%m%d%H%M%S", time.localtime())}.png'
- print(routine_follow_up_payload)
+ NewServicesRevisit.download_url_content(png_url, save_path)
+ logger.info(f"已保存图片到 {save_path}。")
+ up_data = api_instance.get_upload_token(
+ {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b9c63925cd404038a6b86",
+ "transaction_id": UUid})
- res = api_instance.data_batch_create(routine_follow_up_payload)
- logger.info(f"创建结果:{res}")
- time.sleep(1)
- except:
- pass
- common_module.send_task_status(task_start_time, "新签客户回访")
+ upload_url = up_data.get("upload_url")
+ upload_token = up_data.get("upload_token")
+ upload_result = api_instance.upload_file(
+ {"upload_url": upload_url, "upload_token": upload_token, "file_path": save_path})
+ upload_key = upload_result.get("key")
+ logger.info("已上传文件")
+
+ payload_dict.update({
+ "_widget_1734590278279": {"value": row["group_name"]}, # 公司名称
+ "_widget_1735112931760": {"value": row["id_own_group"]}, # 公司id
+ "_widget_1735112931761": {"value": row["id_own_org"]}, # 门店id
+ "_widget_1734590278281": {"value": row['org_name']}, # 门店名称
+ "_widget_1734590278292": {"value": row["跟进阶段"]}, # 跟进阶段
+ "_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
+ "_widget_1742548684369": {"value": row['主要目的']}, # 主要目的
+ "_widget_1734590278266": {"value": row['region_name']}, # 大区
+ "_widget_1734590278285": {"value": row['branch_name']}, # 小区
+ "_widget_1734590278284": {"value": row['province_name']}, # 省
+ "_widget_1734590278283": {"value": row['city_name']}, # 市
+ "_widget_1734590278282": {"value": row['area_name']}, # 区
+ "_widget_1734590278278": {"value": row['saas_customer_type']}, # 门店分层
+ "_widget_1734590278277": {"value": row['group_grade']}, # 公司等级
+ "_widget_1734590278276": {"value": row['limit_user_type']}, # 限制账户类型
+ "_widget_1734590278275": {"value": row['active_user_type']}, # 有效账户类型
+ "_widget_1734590278274": {"value": row['saas_version']}, # ERP操作模式
+ "_widget_1734590278273": {"value": row['saas_use_year']}, # 使用时长
+ "_widget_1734590278272": {"value": row['org_stage']}, # 门店阶段
+ "_widget_1734590278271": {"value": row['manage_model']}, # 经营模式
+ "_widget_1734590278267": {"value": row['contacts']}, # 联系人
+ "_widget_1734590278287": {"value": row['contact_mobile']}, # 联系手机号
+ "_widget_1734590278286": {"value": row['saas_edition_fmt']}, # SaaS版本
+ "_widget_1734590278280": {"value": row['org_code']}, # 门店编码
+ "_widget_1735096489244": {"value": distribution_date}, # 派发时间
+ "_widget_1742895342914": {"value": row['business_scope_fmt']}, # 经营范围
+ "_widget_1742895342915": {"value": row['station_number']}, # 工位数
+ "_widget_1742895342916": {"value": [upload_key]} # 门头照片
+ })
+
+ routine_follow_up_payload = {
+ "api_key": "675b900991ad2491c69389ca",
+ "entry_id": "675b9c63925cd404038a6b86",
+ "is_start_workflow": "true",
+ "data": payload_dict,
+ "transaction_id": UUid
+ }
+
+ res = api_instance.data_batch_create(routine_follow_up_payload)
+ logger.info(f"创建结果:{res}")
+ time.sleep(1)
+ except:
+ pass
+ common_module.send_task_status(task_start_time, "新签客户回访")
+ logger.info("新签客户回访任务完成")
+ except Exception as e:
+ common_module.send_task_error(task_start_time, "新签客户回访", str(e))
+ error_task_logger.error(f"新签客户回访任务执行时发生异常: {e}")
if __name__ == '__main__':
start = NewServicesRevisit()
diff --git a/back_ground_module/revisit_renew_services_90_120_180.py b/back_ground_module/revisit_renew_services_90_120_180.py
index 7cb39ac..4f7f94b 100644
--- a/back_ground_module/revisit_renew_services_90_120_180.py
+++ b/back_ground_module/revisit_renew_services_90_120_180.py
@@ -241,704 +241,713 @@ class RenewServicesRevisit:
def main(self):
import datetime
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # 主店过期,分店设置为主店
- global png_url, upload_key
- self.load_all_data()
- self.date_list = common_module.get_holiday_list() # 获取一年中的节假日
- self.date_one = self.calculate_date_one(start_offset=0)
- print(self.date_one)
- self.data_NGV = common_module.get_ngv_details(days_back=1) # 获取data_NGV 并转为str
- self.index = self.build_index(self.json_list)
+ try:
+ logger.info("开始执行任务")
+ # 主店过期,分店设置为主店
+ global png_url, upload_key
+ self.load_all_data()
+ logger.info("数据加载完成")
+ self.date_list = common_module.get_holiday_list() # 获取一年中的节假日
+ self.date_one = self.calculate_date_one(start_offset=0)
+ self.data_NGV = common_module.get_ngv_details(days_back=1) # 获取data_NGV 并转为str
+ self.index = self.build_index(self.json_list)
- # 将A列和B列的日期字符串转换为日期格式
- data_NGV = self.data_NGV.copy()
- # data_NGV.to_csv("dayin.csv")
- data_NGV['A'] = pd.to_datetime(data_NGV['expiry_time'])
- data_NGV['B'] = pd.to_datetime(data_NGV['renew_date'])
+ # 将A列和B列的日期字符串转换为日期格式
+ data_NGV = self.data_NGV.copy()
+ data_NGV['A'] = pd.to_datetime(data_NGV['expiry_time'])
+ data_NGV['B'] = pd.to_datetime(data_NGV['renew_date'])
- def replace_values(series):
- # 使用条件判断来进行替换
- return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
+ def replace_values(series):
+ # 使用条件判断来进行替换
+ return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
+ # 对整个DataFrame的所有列应用替换函数
- # 对整个DataFrame的所有列应用替换函数
+ # 处理字符串数据并显式指定数据类型
+ data_NGV = data_NGV.apply(replace_values)
- # 处理字符串数据并显式指定数据类型
- data_NGV = data_NGV.apply(replace_values)
- # data_NGV.to_csv("dayinNGV.csv")
+ # 定义优先级顺序
+ edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
+ customer_type_order = ["F", "E", "D", "C", "B", "A"] # 索引越小优先级越高
+ group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']
- # 定义优先级顺序
- edition_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
- customer_type_order = ["F", "E", "D", "C", "B", "A"] # 索引越小优先级越高
- group_grade_order = ['全国KA(FMVP)', '区域KA(MVP)', '重要客户(SVIP)', '普通客户(VIP)']
+ # 创建映射字典,并为不在列表中的值设置默认值
+ edition_map = {edition: idx for idx, edition in enumerate(edition_order)}
+ customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}
+ group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}
- # 创建映射字典,并为不在列表中的值设置默认值
- edition_map = {edition: idx for idx, edition in enumerate(edition_order)}
- customer_type_map = {ctype: idx for idx, ctype in enumerate(customer_type_order)}
- group_grade_map = {grade: idx for idx, grade in enumerate(group_grade_order)}
+ # 添加用于排序的新列,并处理不在映射字典中的值
+ data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(
+ int) # 缺失值用最高优先级填充
+ data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(int)
+ data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)
+ # data_NGV.to_csv("88855.csv")
- # 添加用于排序的新列,并处理不在映射字典中的值
- data_NGV['edition_rank'] = data_NGV['saas_edition_fmt'].map(edition_map).fillna(0).astype(
- int) # 缺失值用最高优先级填充
- data_NGV['customer_type_rank'] = data_NGV['saas_customer_type'].map(customer_type_map).fillna(0).astype(int)
- data_NGV['group_grade_rank'] = data_NGV['group_grade'].map(group_grade_map).fillna(0).astype(int)
- # data_NGV.to_csv("88855.csv")
+ # 找到每组中 edition_rank 最小值对应的行
+ best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()
+ best_edition_rows = data_NGV.loc[best_edition_idx]
+ best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']
- # 找到每组中 edition_rank 最小值对应的行
- best_edition_idx = data_NGV.groupby('id_own_group')['edition_rank'].idxmin()
- best_edition_rows = data_NGV.loc[best_edition_idx]
- best_edition_rows['max_saas_edition'] = best_edition_rows['saas_edition_fmt']
+ # 找到每组中 customer_type_rank 最小值对应的行
+ best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()
+ best_customer_type_rows = data_NGV.loc[best_customer_type_idx]
+ best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(
+ lambda x: customer_type_order[x])
- # 找到每组中 customer_type_rank 最小值对应的行
- best_customer_type_idx = data_NGV.groupby('id_own_group')['customer_type_rank'].idxmin()
- best_customer_type_rows = data_NGV.loc[best_customer_type_idx]
- best_customer_type_rows['max_saas_customer_type'] = best_customer_type_rows['customer_type_rank'].apply(
- lambda x: customer_type_order[x])
+ # 找到每组中 group_grade_rank 最小值对应的行
+ best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()
+ best_group_grade_rows = data_NGV.loc[best_group_grade_idx]
+ best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']
- # 找到每组中 group_grade_rank 最小值对应的行
- best_group_grade_idx = data_NGV.groupby('id_own_group')['group_grade_rank'].idxmin()
- best_group_grade_rows = data_NGV.loc[best_group_grade_idx]
- best_group_grade_rows['max_group_grade'] = best_group_grade_rows['group_grade']
+ # 合并最佳值回到原数据集
+ best_values = (
+ best_edition_rows[['id_own_group', 'max_saas_edition']]
+ .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group',
+ how='outer')
+ .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')
+ )
- # 合并最佳值回到原数据集
- best_values = (
- best_edition_rows[['id_own_group', 'max_saas_edition']]
- .merge(best_customer_type_rows[['id_own_group', 'max_saas_customer_type']], on='id_own_group',
- how='outer')
- .merge(best_group_grade_rows[['id_own_group', 'max_group_grade']], on='id_own_group', how='outer')
- )
+ # 将最佳值合并回原数据集
+ data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
- # 将最佳值合并回原数据集
- data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
+ condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件
- condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期') # 步骤2: 过滤条件
+ ngvv2 = data_NGV[condition]
+ # ngvv2.to_excel(r"C:\Users\Administrator.DESKTOP-7IC2USJ\Desktop\NGVV2.xlsx")
- ngvv2 = data_NGV[condition]
- # ngvv2.to_excel(r"C:\Users\Administrator.DESKTOP-7IC2USJ\Desktop\NGVV2.xlsx")
+ data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中
+ data_NGV_V2['条件'] = ((data_NGV_V2['org_type'] == "一般") & (data_NGV_V2['org_status'] == '留存') &
+ (data_NGV_V2['area_manager'] != '殷昊') & (
+ data_NGV_V2['area_manager'] != '孙玉蕾') & (
+ data_NGV_V2['is_main_org'] != 1))
+ data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2["条件"]]
+ # 步骤4: 过滤存在的记录
+ data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])
+ filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]
- data_NGV_V2 = data_NGV.copy() # 步骤3: 检查id_own_group是否存在于ngvv2中
- data_NGV_V2['条件'] = ((data_NGV_V2['org_type'] == "一般") & (data_NGV_V2['org_status'] == '留存') &
- (data_NGV_V2['area_manager'] != '殷昊') & (data_NGV_V2['area_manager'] != '孙玉蕾') & (
- data_NGV_V2['is_main_org'] != 1))
- data_NGV_V2 = data_NGV_V2.loc[data_NGV_V2["条件"]]
- # 步骤4: 过滤存在的记录
- data_NGV_V2['exists_in_ngvv2'] = data_NGV_V2['id_own_group'].isin(ngvv2['id_own_group'])
- filtered_data = data_NGV_V2[data_NGV_V2['exists_in_ngvv2']]
+ fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
+ # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))
- fixed_order = ['皇冠版', '至尊版', '尊享版', '旗舰版', '标准版', '进阶版', '基础版', '入门版']
- # sorted_items = sorted(filtered_data, key=lambda x: fixed_order.index(x))
+ fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}
+ filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)
+ filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)
- fixed_order_map = {edition: index for index, edition in enumerate(fixed_order)}
- filtered_data['sort_key'] = filtered_data['saas_edition_fmt'].map(fixed_order_map)
- filtered_data = filtered_data.sort_values(by='sort_key').drop('sort_key', axis=1)
+ result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')
- result = filtered_data.drop_duplicates(subset='id_own_group', keep='first')
+ data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
+ data_NGV['area_manager'] != '殷昊') & (
+ data_NGV['area_manager'] != '孙玉蕾') & (
+ data_NGV['is_main_org'] == 1)
+ data_NGV = data_NGV.loc[data_NGV["条件"]]
- data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
- data_NGV['area_manager'] != '殷昊') & (
- data_NGV['area_manager'] != '孙玉蕾') & (
- data_NGV['is_main_org'] == 1)
- data_NGV = data_NGV.loc[data_NGV["条件"]]
+ data_NGV = pd.concat([data_NGV, result], axis=0)
+ data_details = data_NGV.copy()
- data_NGV = pd.concat([data_NGV, result], axis=0)
- # data_NGV.to_csv("dayin1.csv")
- data_details = data_NGV.copy()
- # data_details.to_excel(r"C:\Users\admin\Downloads\1.xlsx")
+ # 重置索引
+ data_details = data_details.reset_index(drop=True)
+ # data_details.to_csv("dayin.csv")
+ # 判断A列的日期是否大于B列的日期730天,如果是的话,将B列的值设置为1
+ data_details['条件'] = data_details.apply(
+ lambda row: (
+ (pd.to_datetime(row['A']) - pd.to_datetime(row['B'])).days
+ if pd.to_datetime(row['A']) - pd.to_datetime(row['B']) >= pd.Timedelta(days=730)
+ else 0
+ ),
+ axis=1
+ )
+ data_details = data_details.loc[data_details["条件"] > 0]
- # 重置索引
- data_details = data_details.reset_index(drop=True)
- # data_details.to_csv("dayin.csv")
- # 判断A列的日期是否大于B列的日期730天,如果是的话,将B列的值设置为1
- data_details['条件'] = data_details.apply(
- lambda row: (
- (pd.to_datetime(row['A']) - pd.to_datetime(row['B'])).days
- if pd.to_datetime(row['A']) - pd.to_datetime(row['B']) >= pd.Timedelta(days=730)
- else 0
- ),
- axis=1
- )
- data_details = data_details.loc[data_details["条件"] > 0]
+ # 定义一个函数,用于将数字除以365并取整数
+ def divide_by_365(x):
+ if isinstance(x, (int, float)):
+ return int(x / 365)
+ else:
+ return x
- # 定义一个函数,用于将数字除以365并取整数
- def divide_by_365(x):
- if isinstance(x, (int, float)):
- return int(x / 365)
- else:
- return x
+ # 使用applymap()函数将divide_by_365函数应用到DataFrame的每个元素
+ data_details['年'] = data_details['条件'].apply(divide_by_365)
+ # 重置索引
+ data_details = data_details.reset_index(drop=True)
+ # data_details.to_excel(r"C:\Users\admin\Downloads\2.xlsx")
+ # 创建一个新的空的DataFrame
+ new_df = pd.DataFrame()
+ # 遍历原始DataFrame的每一行
+ from datetime import datetime
+ for index, row in data_details.iterrows():
+ # 根据A列的值来决定复制的次数
+ if row["renew_date"] != "2024-02-29":
+ for i_new in range(1, row['年']):
+ # 修改日期
+ row_new = row.copy()
+ c = row_new["renew_date"]
+ date_obj = datetime.strptime(c, "%Y-%m-%d")
+ new_year = date_obj.year + i_new
+ new_date_obj = date_obj.replace(year=new_year)
+ new_c = new_date_obj.strftime("%Y-%m-%d")
+ row_new["renew_date"] = new_c
+ # 将当前行添加到新的DataFrame中
+ # new_df = new_df.append(row_new, ignore_index=True)
+ new_df = pd.concat([new_df, pd.DataFrame([row_new])], ignore_index=True)
+ # 合并两个DataFrame
+ merged_df = pd.concat([data_NGV, new_df], axis=0, ignore_index=True)
+ data_details = merged_df.copy() # 替换名称
- # 使用applymap()函数将divide_by_365函数应用到DataFrame的每个元素
- data_details['年'] = data_details['条件'].apply(divide_by_365)
- # 重置索引
- data_details = data_details.reset_index(drop=True)
- # data_details.to_excel(r"C:\Users\admin\Downloads\2.xlsx")
- # 创建一个新的空的DataFrame
- new_df = pd.DataFrame()
- # 遍历原始DataFrame的每一行
- from datetime import datetime
- for index, row in data_details.iterrows():
- # 根据A列的值来决定复制的次数
- if row["renew_date"] != "2024-02-29":
- for i_new in range(1, row['年']):
- # 修改日期
- row_new = row.copy()
- c = row_new["renew_date"]
- date_obj = datetime.strptime(c, "%Y-%m-%d")
- new_year = date_obj.year + i_new
- new_date_obj = date_obj.replace(year=new_year)
- new_c = new_date_obj.strftime("%Y-%m-%d")
- row_new["renew_date"] = new_c
- # 将当前行添加到新的DataFrame中
- # new_df = new_df.append(row_new, ignore_index=True)
- new_df = pd.concat([new_df, pd.DataFrame([row_new])], ignore_index=True)
- # 合并两个DataFrame
- # new_df.to_excel(r"C:\Users\admin\Downloads\3.xlsx")
- merged_df = pd.concat([data_NGV, new_df], axis=0, ignore_index=True)
- data_details = merged_df.copy() # 替换名称
+ data_details_not_null = data_details[data_details['renew_date'].notnull()]
+ # data_details_not_null = data_details_not_null[data_details_not_null['renew_date'].str.contains('2023')]
+ # data_details_not_null = data_details_not_null.sort_values(by='renew_date', ascending=True).drop_duplicates(
+ # subset='id_own_group') 重置索引
+ data_details_not_null = data_details_not_null.reset_index(drop=True)
+ data_details = data_details_not_null.copy() # 替换名称 v2
+ data_details['saas_create_time'] = data_details['saas_create_time'].str[:4] # 截取前10位
+ data_details['renew_date_new'] = data_details['renew_date'].str[:4] # 截取前10位
+ data_details = data_details[
+ data_details['saas_create_time'] != data_details['renew_date_new']] # 过滤掉等于renew_date的行
- data_details_not_null = data_details[data_details['renew_date'].notnull()]
- # data_details_not_null = data_details_not_null[data_details_not_null['renew_date'].str.contains('2023')]
- # data_details_not_null = data_details_not_null.sort_values(by='renew_date', ascending=True).drop_duplicates(
- # subset='id_own_group') 重置索引
- data_details_not_null = data_details_not_null.reset_index(drop=True)
- data_details = data_details_not_null.copy() # 替换名称 v2
- data_details['saas_create_time'] = data_details['saas_create_time'].str[:4] # 截取前10位
- data_details['renew_date_new'] = data_details['renew_date'].str[:4] # 截取前10位
- data_details = data_details[
- data_details['saas_create_time'] != data_details['renew_date_new']] # 过滤掉等于renew_date的行
+ data_details = data_details.reset_index(drop=True)
- data_details = data_details.reset_index(drop=True)
-
- print(data_details)
- # data_details.to_excel(r"C:\Users\admin\Downloads\4.xlsx")
- import datetime
- start_time = datetime.datetime.now()
-
- date_90 = 83
- date_120 = 113
- date_180 = 173
- # self.date_one = 1
- now_time = start_time.replace()
-
- if now_time.strftime("%Y-%m-%d") in self.date_list:
- self.date_one = 0
- print("开始次数:", self.date_one)
- print("当前日期:", now_time)
-
- # for i in range(1, 10):
- # new_date = now_time + datetime.timedelta(days=-i)
- # new_date = new_date.strftime("%Y-%m-%d")
- # print("遍历日期:", new_date)
- # if new_date in self.date_list:
- # date_one = date_one + 1
- # print("节假日期:", new_date)
- # else:
- # break
-
- print("遍历次数:", self.date_one)
-
- now_time = start_time.replace()
- for i in range(0, self.date_one):
- print(f"这是第{i}次遍历")
+ logger.info(f"过滤后的数据长度为: {len(data_details)}")
+ # data_details.to_excel(r"C:\Users\admin\Downloads\4.xlsx")
import datetime
- now_time = datetime.datetime.now() + datetime.timedelta(days=-(i + 1))
+ start_time = datetime.datetime.now()
- today = now_time + datetime.timedelta(days=-date_90)
- formatted_today_90 = today.strftime("%Y-%m-%d")
- today = now_time + datetime.timedelta(days=-date_120)
- formatted_today_120 = today.strftime("%Y-%m-%d")
- today = now_time + datetime.timedelta(days=-date_180)
- formatted_today_180 = today.strftime("%Y-%m-%d")
- print(formatted_today_90, formatted_today_120, formatted_today_180)
- # 获取数据
- data_details_90 = data_details.copy()
- data_details_90['条件'] = (data_details_90['renew_date'] == formatted_today_90) & (data_details_90[
- 'group_grade'] != "普通客户(VIP)") # & (data_details_90['saas_edition_fmt'] != '基础版') & (data_details_90['saas_edition_fmt'] != '入门版')
- data_details_90 = data_details_90.loc[data_details_90["条件"]]
- data_details_120 = data_details.copy()
- data_details_120['条件'] = (data_details_120['renew_date'] == formatted_today_120) & (
- (data_details_120['saas_edition_fmt'] == '基础版') | (
- data_details_120['saas_edition_fmt'] == '入门版'))
- data_details_120 = data_details_120.loc[data_details_120["条件"]]
- data_details_180 = data_details.copy()
- data_details_180['条件'] = (data_details_180[
- 'renew_date'] == formatted_today_180) # & (data_details_180[
- # 'saas_edition_fmt'] != '基础版') & (data_details_180['saas_edition_fmt'] != '入门版')
- data_details_180 = data_details_180.loc[data_details_180["条件"]]
- data_details_90["跟进阶段"] = "续约后90天回访"
- data_details_90["主要目的"] = "关怀使用情况,促进更多功能使用,提升系统使用深度。"
- data_details_120["跟进阶段"] = "续约后120天回访"
- data_details_120["主要目的"] = "暂无"
- data_details_180["跟进阶段"] = "续约后180天回访"
- data_details_180["主要目的"] = "关怀使用情况,促进增购商机转化,识别潜在风险,及时提报。"
+ date_90 = 83
+ date_120 = 113
+ date_180 = 173
+ # self.date_one = 1
+ now_time = start_time.replace()
- # 合并三个DataFrame
- data_result = pd.concat([data_details_90, data_details_180],
- ignore_index=True) # 去除续约120天回访 data_details_120
- print(len(data_result))
- data_result = data_result.astype(str)
+ if now_time.strftime("%Y-%m-%d") in self.date_list:
+ self.date_one = 0
+ print("开始次数:", self.date_one)
+ print("当前日期:", now_time)
- data_NGV = data_result.copy()
+ logger.info(f"遍历次数:{self.date_one}")
- for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
- try:
- # print(row["org_code"]) # 数据验证
- # print(row["service_impl_principal"])
- # print(row["area_manager"])
- # print(row["technician"])
- print("销售负责人是:", row["salesmen"])
+ now_time = start_time.replace()
+ for i in range(0, self.date_one):
+ logger.info(f"这是第{i}次遍历")
+ import datetime
+ now_time = datetime.datetime.now() + datetime.timedelta(days=-(i + 1))
- payload_dict = {}
- saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
+ today = now_time + datetime.timedelta(days=-date_90)
+ formatted_today_90 = today.strftime("%Y-%m-%d")
+ today = now_time + datetime.timedelta(days=-date_120)
+ formatted_today_120 = today.strftime("%Y-%m-%d")
+ today = now_time + datetime.timedelta(days=-date_180)
+ formatted_today_180 = today.strftime("%Y-%m-%d")
+ logger.info(f"90天为{formatted_today_90},180天为{formatted_today_180}")
- NGV_roles = {
- 'relationship_manager': row['service_impl_principal'], # 运营负责人
- # 'relationship_manager': "张阳", # 运营负责人
- 'area_manager': row['area_manager'], # 区域经理
- 'technician': row['technician'], # 技术专家
- 'salesmen': row['salesmen'], # 销售负责人
- }
+ # 获取数据
+ data_details_90 = data_details.copy()
+ data_details_90['条件'] = (data_details_90['renew_date'] == formatted_today_90) & (data_details_90[
+ 'group_grade'] != "普通客户(VIP)") # & (data_details_90['saas_edition_fmt'] != '基础版') & (data_details_90['saas_edition_fmt'] != '入门版')
+ data_details_90 = data_details_90.loc[data_details_90["条件"]]
+ data_details_120 = data_details.copy()
+ data_details_120['条件'] = (data_details_120['renew_date'] == formatted_today_120) & (
+ (data_details_120['saas_edition_fmt'] == '基础版') | (
+ data_details_120['saas_edition_fmt'] == '入门版'))
+ data_details_120 = data_details_120.loc[data_details_120["条件"]]
+ data_details_180 = data_details.copy()
+ data_details_180['条件'] = (data_details_180[
+ 'renew_date'] == formatted_today_180) # & (data_details_180[
+ # 'saas_edition_fmt'] != '基础版') & (data_details_180['saas_edition_fmt'] != '入门版')
+ data_details_180 = data_details_180.loc[data_details_180["条件"]]
+ data_details_90["跟进阶段"] = "续约后90天回访"
+ data_details_90["主要目的"] = "关怀使用情况,促进更多功能使用,提升系统使用深度。"
+ data_details_120["跟进阶段"] = "续约后120天回访"
+ data_details_120["主要目的"] = "暂无"
+ data_details_180["跟进阶段"] = "续约后180天回访"
+ data_details_180["主要目的"] = "关怀使用情况,促进增购商机转化,识别潜在风险,及时提报。"
+
+ # 合并三个DataFrame
+ data_result = pd.concat([data_details_90, data_details_180],
+ ignore_index=True) # 去除续约120天回访 data_details_120
+ logger.info(f"派发数据长度:{len(data_result)}")
+ data_result = data_result.astype(str)
+
+ data_NGV = data_result.copy()
+
+ for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
+ try:
+ # print(row["org_code"]) # 数据验证
+ # print(row["service_impl_principal"])
+ # print(row["area_manager"])
+ # print(row["technician"])
+ # print("销售负责人是:", row["salesmen"])
+
+ payload_dict = {}
+ saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
+
+ NGV_roles = {
+ 'relationship_manager': row['service_impl_principal'], # 运营负责人
+ # 'relationship_manager': "张阳", # 运营负责人
+ 'area_manager': row['area_manager'], # 区域经理
+ 'technician': row['technician'], # 技术专家
+ 'salesmen': row['salesmen'], # 销售负责人
+ }
+
+ for role, name in NGV_roles.items():
+ for row_item in self.staff_id_list:
+ staff_id = self.get_staff_id(row_item, name)
+ if staff_id:
+ NGV_roles[role] = staff_id
+ break # 找到后退出循环
+ else:
+ NGV_roles[role] = None # 如果没有找到对应的员工ID
+ # 回访人员: 需确认 四年以下 technician
+
+ if int(saas_use_year) < 4:
+ relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
+ ['relationship_manager',
+ 'area_manager',
+ 'technician', 'salesmen']]
+ # 如果未找到运营负责人,则根据省市区派发给日常回访客服
+ if not relationship_manager:
+ relationship_manager = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
+ )[0]
+ if not technician:
+ technician = self.assign_customer_service(
+ row['province_name'], row['city_name'], row['area_name'], self.index
+ )[2]
+
+ if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
+ payload_dict.update({
+ "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
+ })
+ else:
+ payload_dict.update({
+ "_widget_1734590278288": {"value": technician}, # 跟进人是技术专家
+ })
- for role, name in NGV_roles.items():
- for row_item in self.staff_id_list:
- staff_id = self.get_staff_id(row_item, name)
- if staff_id:
- NGV_roles[role] = staff_id
- break # 找到后退出循环
else:
- NGV_roles[role] = None # 如果没有找到对应的员工ID
- # 回访人员: 需确认 四年以下 technician
- if int(saas_use_year) < 4:
-
- relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
- ['relationship_manager',
- 'area_manager',
- 'technician', 'salesmen']]
- # 如果未找到运营负责人,则根据省市区派发给日常回访客服
- if not relationship_manager:
- relationship_manager = self.assign_customer_service(
+ logger.info(
+ f"超过4年的客户,派发给客服,省市区:{row['province_name']} {row['city_name']} {row['area_name']}")
+ salesmen = [NGV_roles[role] for role in ['salesmen']][0]
+ # 直接根据省市区派发给日常回访客服
+ relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(
row['province_name'], row['city_name'], row['area_name'], self.index
- )[0]
- if not technician:
- technician = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )[2]
+ )
+ logger.info(f"派发给 {relationship_manager} {customer_service} {technician} {area_manager}")
- if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
- payload_dict.update({
- "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
- })
- else:
- payload_dict.update({
- "_widget_1734590278288": {"value": technician}, # 跟进人是技术专家
- })
+ if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
+ payload_dict.update({
+ "_widget_1734590278288": {"value": customer_service} # 跟进人是日常回访客服
+ })
+ else:
+ payload_dict.update({
+ "_widget_1734590278288": {"value": technician} # 跟进人是技术专家
+ })
- else:
- salesmen = [NGV_roles[role] for role in ['salesmen']][0]
- # print(salesmen)
- # salesmen = [NGV_roles[role] for role in
- # ['salesmen']]
- # 直接根据省市区派发给日常回访客服
- relationship_manager, customer_service, technician, area_manager = self.assign_customer_service(
- row['province_name'], row['city_name'], row['area_name'], self.index
- )
-
- if row["group_grade"] == "普通客户(VIP)" or row["group_grade"] == "重要客户(SVIP)":
- payload_dict.update({
- "_widget_1734590278288": {"value": customer_service} # 跟进人是日常回访客服
- })
- else:
- payload_dict.update({
- "_widget_1734590278288": {"value": technician} # 跟进人是技术专家
- })
-
- payload_dict.update({
- # "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
- "_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
- "_widget_1734590278290": {"value": area_manager}, # 区域经理
- "_widget_1734590278291": {"value": technician}, # 技术专家
- "_widget_1735290738545": {"value": salesmen} # 销售负责人
- })
-
- if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
payload_dict.update({
- "_widget_1734590278288": {"value": "051612246035720178"}, # 跟进人是赵柄诚
+ # "_widget_1734590278288": {"value": relationship_manager}, # 跟进人是运营负责人
+ "_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
+ "_widget_1734590278290": {"value": area_manager}, # 区域经理
+ "_widget_1734590278291": {"value": technician}, # 技术专家
+ "_widget_1735290738545": {"value": salesmen} # 销售负责人
})
+ logger.info(f"请求输出:{payload_dict}")
- # 输出结果
- print("SaaS开户回访人员:", relationship_manager or "未分配")
- print("SaaS技术专家:", technician or "未分配")
- print("SaaS区域经理:", area_manager or "未分配")
+ if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
+ payload_dict.update({
+ "_widget_1734590278288": {"value": "051612246035720178"}, # 跟进人是赵柄诚
+ })
- # 判断权限唯一值
- # pattern = r'([\u4e00-\u9fa5]+)\('
- # match = re.search(pattern, row['max_group_grade'])
- # group_grade = match.group(1)
- group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
+ # 输出结果
+ logger.info(f"SaaS开户回访人员:{relationship_manager}")
+ logger.info(f"SaaS技术专家:{technician}")
+ logger.info(f"SaaS区域经理:{area_manager}")
- if not row['saas_customer_type'] or row['saas_customer_type'] == 'NA' or row[
- 'saas_customer_type'] == 'None':
- row['saas_customer_type'] = "F"
+ # 判断权限唯一值
+ group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
- NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
- print("权限唯一值:", NGV_store_level_key)
+ if not row['saas_customer_type'] or row['saas_customer_type'] == 'NA' or row[
+ 'saas_customer_type'] == 'None':
+ row['saas_customer_type'] = "F"
- Billing = None
- for item in self.permissions_table:
- if NGV_store_level_key == item.get("_widget_1734056507963"): # 合并(等级-类型-分层)
- print("该门店开单的权限是:", item.get("_widget_1734055617039"))
- Billing = item.get("_widget_1734055617039") # 开单
- Service_Alerts = item.get("_widget_1734055617040") # 服务提醒
- membership = item.get("_widget_1734055617041") # 会员卡
- SMS = item.get("_widget_1734055617042") # 短信
- Public_domain_applets = item.get("_widget_1734055617043") # 公域小程序
- Private_domain_applets = item.get("_widget_1734055617044") # 私域小程序
- Test_sheet = item.get("_widget_1734055617045") # 检测单
- AI_poster = item.get("_widget_1734055617046") # AI海报
- Business_wallets = item.get("_widget_1734055617047") # 企业钱包
- Precision_marketing = item.get("_widget_1734055617049") # 精准营销
- Paid_memberships = item.get("_widget_1734055617051") # 付费会员
- business_WeCom = item.get("_widget_1734055617052") # 企业微信
- Insurance_policy_identification = item.get("_widget_1734055617053") # 保险单识别
- Insurance_bots = item.get("_widget_1734055617054") # 保险机器人
- Camera_pick_up = item.get("_widget_1734055617055") # 摄像头接车
- Camera_billing = item.get("_widget_1734055617056") # 摄像头开单
- Transparent_workshop = item.get("_widget_1734055617057") # 透明车间
- Cross_industry_cooperation = item.get("_widget_1734055617058") # 异业合作
- BI_Insights = item.get("_widget_1734055617059") # BI洞察
- payload_dict.update(
- {
- "_widget_1734073342350": {"value": Billing},
- "_widget_1735004315757": {"value": Service_Alerts},
- "_widget_1735004315756": {"value": membership},
- "_widget_1735004315755": {"value": SMS},
- "_widget_1735004315754": {"value": Public_domain_applets},
- "_widget_1735004315753": {"value": Private_domain_applets},
- "_widget_1735004315752": {"value": Test_sheet},
- "_widget_1735004315751": {"value": AI_poster},
- "_widget_1735004315750": {"value": Business_wallets},
- "_widget_1735004315749": {"value": Precision_marketing},
- "_widget_1735004315748": {"value": Paid_memberships},
- "_widget_1735004315747": {"value": business_WeCom},
- "_widget_1735004315746": {"value": Insurance_policy_identification},
- "_widget_1735004315745": {"value": Insurance_bots},
- "_widget_1735004315744": {"value": Camera_pick_up},
- "_widget_1735004315743": {"value": Camera_billing},
- "_widget_1735004315742": {"value": Transparent_workshop},
- "_widget_1735004315741": {"value": Cross_industry_cooperation},
- "_widget_1734073342352": {"value": BI_Insights},
+ NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
+ logger.info(f"权限唯一值: {NGV_store_level_key}")
+
+ Billing = None
+ for item in self.permissions_table:
+ if NGV_store_level_key == item.get("_widget_1734056507963"): # 合并(等级-类型-分层)
+ print("该门店开单的权限是:", item.get("_widget_1734055617039"))
+ Billing = item.get("_widget_1734055617039") # 开单
+ Service_Alerts = item.get("_widget_1734055617040") # 服务提醒
+ membership = item.get("_widget_1734055617041") # 会员卡
+ SMS = item.get("_widget_1734055617042") # 短信
+ Public_domain_applets = item.get("_widget_1734055617043") # 公域小程序
+ Private_domain_applets = item.get("_widget_1734055617044") # 私域小程序
+ Test_sheet = item.get("_widget_1734055617045") # 检测单
+ AI_poster = item.get("_widget_1734055617046") # AI海报
+ Business_wallets = item.get("_widget_1734055617047") # 企业钱包
+ Precision_marketing = item.get("_widget_1734055617049") # 精准营销
+ Paid_memberships = item.get("_widget_1734055617051") # 付费会员
+ business_WeCom = item.get("_widget_1734055617052") # 企业微信
+ Insurance_policy_identification = item.get("_widget_1734055617053") # 保险单识别
+ Insurance_bots = item.get("_widget_1734055617054") # 保险机器人
+ Camera_pick_up = item.get("_widget_1734055617055") # 摄像头接车
+ Camera_billing = item.get("_widget_1734055617056") # 摄像头开单
+ Transparent_workshop = item.get("_widget_1734055617057") # 透明车间
+ Cross_industry_cooperation = item.get("_widget_1734055617058") # 异业合作
+ BI_Insights = item.get("_widget_1734055617059") # BI洞察
+ payload_dict.update(
+ {
+ "_widget_1734073342350": {"value": Billing},
+ "_widget_1735004315757": {"value": Service_Alerts},
+ "_widget_1735004315756": {"value": membership},
+ "_widget_1735004315755": {"value": SMS},
+ "_widget_1735004315754": {"value": Public_domain_applets},
+ "_widget_1735004315753": {"value": Private_domain_applets},
+ "_widget_1735004315752": {"value": Test_sheet},
+ "_widget_1735004315751": {"value": AI_poster},
+ "_widget_1735004315750": {"value": Business_wallets},
+ "_widget_1735004315749": {"value": Precision_marketing},
+ "_widget_1735004315748": {"value": Paid_memberships},
+ "_widget_1735004315747": {"value": business_WeCom},
+ "_widget_1735004315746": {"value": Insurance_policy_identification},
+ "_widget_1735004315745": {"value": Insurance_bots},
+ "_widget_1735004315744": {"value": Camera_pick_up},
+ "_widget_1735004315743": {"value": Camera_billing},
+ "_widget_1735004315742": {"value": Transparent_workshop},
+ "_widget_1735004315741": {"value": Cross_industry_cooperation},
+ "_widget_1734073342352": {"value": BI_Insights},
+
+ }
+ )
+
+ feature_dict = {
+ "开单": "_widget_1734073342350",
+ "服务提醒": "_widget_1735004315757",
+ "会员卡": "_widget_1735004315756",
+ "短信": "_widget_1735004315755",
+ "公域小程序": "_widget_1735004315754",
+ "私域小程序": "_widget_1735004315753",
+ "检测单": "_widget_1735004315752",
+ "AI海报": "_widget_1735004315751",
+ "企业钱包": "_widget_1735004315750",
+ "精准营销": "_widget_1735004315749",
+ "付费会员": "_widget_1735004315748",
+ "企业微信": "_widget_1735004315747",
+ "保险单识别": "_widget_1735004315746",
+ "保险机器人": "_widget_1735004315745",
+ "摄像头接车": "_widget_1735004315744",
+ "摄像头开单": "_widget_1735004315743",
+ "透明车间": "_widget_1735004315742",
+ "异业合作": "_widget_1735004315741",
+ "BI洞察": "_widget_1734073342352",
}
- )
+ # _widget_1735527329557 下次是否推荐
+ for new_item in self.get_feature_usage:
+ for feature_module, feature_value in feature_dict.items(): # 模块
+ if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
+ "_widget_1735527329557") == "否" and new_item.get(
+ "_widget_1735280720550") == \
+ row["id_own_org"]: # 下次是否推荐 功能使用情况表
+ logger.info(f"{feature_value}进行了更改")
- feature_dict = {
- "开单": "_widget_1734073342350",
- "服务提醒": "_widget_1735004315757",
- "会员卡": "_widget_1735004315756",
- "短信": "_widget_1735004315755",
- "公域小程序": "_widget_1735004315754",
- "私域小程序": "_widget_1735004315753",
- "检测单": "_widget_1735004315752",
- "AI海报": "_widget_1735004315751",
- "企业钱包": "_widget_1735004315750",
- "精准营销": "_widget_1735004315749",
- "付费会员": "_widget_1735004315748",
- "企业微信": "_widget_1735004315747",
- "保险单识别": "_widget_1735004315746",
- "保险机器人": "_widget_1735004315745",
- "摄像头接车": "_widget_1735004315744",
- "摄像头开单": "_widget_1735004315743",
- "透明车间": "_widget_1735004315742",
- "异业合作": "_widget_1735004315741",
- "BI洞察": "_widget_1734073342352",
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
- }
- # _widget_1735527329557 下次是否推荐
- for new_item in self.get_feature_usage:
- for feature_module, feature_value in feature_dict.items(): # 模块
- if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
- "_widget_1735527329557") == "否" and new_item.get(
- "_widget_1735280720550") == \
- row["id_own_org"]: # 下次是否推荐 功能使用情况表
- print(f"{feature_value}进行了更改")
- payload_dict.update({f"{feature_value}": {"value": "×"}})
+ if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
+ "_widget_1736414617462") == "否" and new_item.get(
+ "_widget_1735280720550") == \
+ row["id_own_org"]: # 下次是否跟进
+ logger.info(f"{feature_value}进行了更改")
- if new_item.get("_widget_1735268263079") == feature_module and new_item.get(
- "_widget_1736414617462") == "否" and new_item.get(
- "_widget_1735280720550") == \
- row["id_own_org"]: # 下次是否跟进
- print(f"{feature_value}进行了更改")
- payload_dict.update({f"{feature_value}": {"value": "×"}})
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
- fields_to_check = {
- "_widget_1735004315763": Billing, # 开单
- "_widget_1735106258016": Service_Alerts, # 服务提醒
- "_widget_1735106258036": membership, # 会员卡
- "_widget_1735106258086": SMS, # 短信
- "_widget_1735106258112": Public_domain_applets, # 公域小程序
- "_widget_1735106258141": Private_domain_applets, # 私域小程序
- "_widget_1735107354648": Test_sheet, # 检测单
- "_widget_1735107354725": AI_poster, # AI海报
- "_widget_1735107354811": Business_wallets, # 企业钱包
- "_widget_1735107354906": Precision_marketing, # 精准营销
- "_widget_1735107354980": Paid_memberships, # 付费会员
- "_widget_1735107355093": business_WeCom, # 企业微信
- "_widget_1735107355143": Insurance_policy_identification, # 保险单识别
- "_widget_1735107355235": Insurance_bots, # 保险机器人
- "_widget_1735107355333": Camera_pick_up, # 摄像头接车
- "_widget_1735107355392": Camera_billing, # 摄像头开单
- "_widget_1735107355502": Transparent_workshop, # 透明车间
- "_widget_1735107355618": Cross_industry_cooperation, # 异业合作
- "_widget_1735107355740": BI_Insights # BI洞察
- }
+ fields_to_check = {
+ "_widget_1735004315763": Billing, # 开单
+ "_widget_1735106258016": Service_Alerts, # 服务提醒
+ "_widget_1735106258036": membership, # 会员卡
+ "_widget_1735106258086": SMS, # 短信
+ "_widget_1735106258112": Public_domain_applets, # 公域小程序
+ "_widget_1735106258141": Private_domain_applets, # 私域小程序
+ "_widget_1735107354648": Test_sheet, # 检测单
+ "_widget_1735107354725": AI_poster, # AI海报
+ "_widget_1735107354811": Business_wallets, # 企业钱包
+ "_widget_1735107354906": Precision_marketing, # 精准营销
+ "_widget_1735107354980": Paid_memberships, # 付费会员
+ "_widget_1735107355093": business_WeCom, # 企业微信
+ "_widget_1735107355143": Insurance_policy_identification, # 保险单识别
+ "_widget_1735107355235": Insurance_bots, # 保险机器人
+ "_widget_1735107355333": Camera_pick_up, # 摄像头接车
+ "_widget_1735107355392": Camera_billing, # 摄像头开单
+ "_widget_1735107355502": Transparent_workshop, # 透明车间
+ "_widget_1735107355618": Cross_industry_cooperation, # 异业合作
+ "_widget_1735107355740": BI_Insights # BI洞察
+ }
- # 遍历每个字段,检查其值并更新payload_dict
- for widget_id, field_name in fields_to_check.items():
- if field_name == "√":
- payload_dict.update({widget_id: {"value": "是"}})
+ # 遍历每个字段,检查其值并更新payload_dict
+ for widget_id, field_name in fields_to_check.items():
+ if field_name == "√":
+ payload_dict.update({widget_id: {"value": "是"}})
- break
-
- is_continue = False
- # 如果门店倒闭则不派发
- for store in self.NGV_data_list:
- if row["id_own_org"] == store.get("_widget_1734062123069") and store.get(
- "_widget_1752027386523") == "门店倒闭":
- is_continue = True
- print(f"门店已关闭,不派发")
- break
- if is_continue:
- continue
-
- if not Billing:
- print(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
-
- if row["active_status_fmt"] == "活跃": # 开单 是否使用
- payload_dict.update({"_widget_1735004315765": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735004315765": {"value": "否"}})
-
- try:
- if row["saas_edition_fmt"] not in ["基础版", "入门版"]: # 会员卡 是否拥有
- payload_dict.update({"_widget_1735106258036": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735106258036": {"value": "否"}})
- except Exception as e:
- print(f"会员卡识别:Error finding customer service: {e}")
-
- try:
- if row["card_bill_day_count_last_30_day"] != "0": # 会员卡 是否使用
- payload_dict.update({"_widget_1735106258038": {"value": "是"}})
- else:
- payload_dict.update({"_widget_1735106258038": {"value": "否"}})
- except Exception as e:
- print(f"会员卡识别:Error finding customer service: {e}")
-
- # print(self.service_remind.get("_widget_1735112637045"))
- payload_dict["_widget_1735106258018"] = {"value": "否"}
-
- for item in self.service_remind:
- if row["id_own_group"] == item.get("_widget_1735112637043"):
- if int(item.get("_widget_1735112637045")) < 180 and int(
- item.get("_widget_1735112637046")) == 1: # 服务提醒 是否使用
- payload_dict.update({"_widget_1735106258018": {"value": "是"}})
- break
- elif int(item.get("_widget_1735112637048")) > 0:
- payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- keys_to_check = [
- "_widget_1735113110155"
- ] # 智能检测 是否使用
+ is_continue = False
+ # 如果门店倒闭则不派发
+ for store in self.NGV_data_list:
+ if row["id_own_org"] == store.get("_widget_1734062123069") and store.get(
+ "_widget_1752027386523") == "门店倒闭":
+ is_continue = True
+ logger.info(f"{row["id_own_org"]}门店已关闭,不派发")
- # 初始化默认值为"否"
- payload_dict["_widget_1735107354650"] = {"value": "否"}
+ break
+ if is_continue:
+ continue
- # 检查每个键,如果有一个大于0,则更新为"是"并停止检查
- for key in keys_to_check:
- for item in self.Smart_detection:
- if row["id_own_org"] == item.get("_widget_1735113110147"):
- if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况
- payload_dict["_widget_1735107354650"]["value"] = "是"
- break
+ if not Billing:
+ logger.warning(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
- # 近30天业务单量=0 则其它所有模块均不推荐
- try:
- for feature_module, feature_value in feature_dict.items(): # 模块
- if row["bill_count_last_30_day"] == '0' and payload_dict[feature_value]["value"] == '△':
- payload_dict.update({f"{feature_value}": {"value": "×"}})
- except Exception as e:
- print(f"不开单识别:Error finding customer service: {e}")
- # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐
- try:
- if row["org_code"] in self.widget_list:
- payload_dict.update({'_widget_1735004315746': {"value": "△"}})
- except Exception as e:
- print(f"保单识别:Error finding customer service: {e}")
-
- # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
- try:
- for item in self.private_domain:
- if row["id_own_group"] == item.get("_widget_1742795002375"): # 公司id
- if int(item.get("_widget_1742795002379")) > 0: # 上架商品数
- payload_dict.update({"_widget_1735106258143": {"value": "是"}}) # DX:是否拥有
- break
- else:
- payload_dict.update({"_widget_1735106258143": {"value": "否"}}) # DX:是否拥有
- break
- except Exception as e:
- print(f"私域小程序:Error finding customer service: {e}")
- try:
- high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']
- if row["saas_edition_fmt"] in high_version:
- payload_dict.update({'_widget_1735106258141': {"value": "是"}}) # SYXCX:是否拥有
+ if row["active_status_fmt"] == "活跃": # 开单 是否使用
+ payload_dict.update({"_widget_1735004315765": {"value": "是"}})
else:
- payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
- except Exception as e:
- print(f"私域小程序:Error finding customer service: {e}")
+ payload_dict.update({"_widget_1735004315765": {"value": "否"}})
- # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
- try:
- for item in self.public_domain:
- if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
- if int(item.get("_widget_1742784257509")) == 1: # 发布商品数量
- payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
+ try:
+ if row["saas_edition_fmt"] not in ["基础版", "入门版"]: # 会员卡 是否拥有
+ payload_dict.update({"_widget_1735106258036": {"value": "是"}})
+ else:
+ payload_dict.update({"_widget_1735106258036": {"value": "否"}})
+ except Exception as e:
+ error_task_logger.error(f"会员卡拥有识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-会员卡拥有识别", str(e))
+
+ try:
+ if row["card_bill_day_count_last_30_day"] != "0": # 会员卡 是否使用
+ payload_dict.update({"_widget_1735106258038": {"value": "是"}})
+ else:
+ payload_dict.update({"_widget_1735106258038": {"value": "否"}})
+ except Exception as e:
+ error_task_logger.error(f"会员卡使用识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-会员卡使用识别", str(e))
+
+ # print(self.service_remind.get("_widget_1735112637045"))
+ payload_dict["_widget_1735106258018"] = {"value": "否"}
+
+ for item in self.service_remind:
+ if row["id_own_group"] == item.get("_widget_1735112637043"):
+ if int(item.get("_widget_1735112637045")) < 180 and int(
+ item.get("_widget_1735112637046")) == 1: # 服务提醒 是否使用
+ payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- else:
- payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
+ elif int(item.get("_widget_1735112637048")) > 0:
+ payload_dict.update({"_widget_1735106258018": {"value": "是"}})
break
- except Exception as e:
- print(f"公域小程序:Error finding customer service: {e}")
- try:
- if row["id_own_org"] in self.public_domain_list:
- payload_dict.update({'_widget_1735106258112': {"value": "是"}}) # GYXCX:是否拥有
- else:
- payload_dict.update({'_widget_1735106258112': {"value": "否"}}) # GYXCX:是否拥有
- except Exception as e:
- print(f"公域小程序:Error finding customer service: {e}")
- # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字
- try:
- if row["id_own_org"] in self.different_industries_list:
- payload_dict.update({'_widget_1735107355618': {"value": "是"}}) # YYHZ:是否拥有
- else:
- payload_dict.update({'_widget_1735107355618': {"value": "否"}}) # YYHZ:是否拥有
- except Exception as e:
- print(f"异业合作:Error finding customer service: {e}")
+ keys_to_check = [
+ "_widget_1735113110155"
+ ] # 智能检测 是否使用
- # 短信:根据是否启动短信功能判断是否拥有,根据
- try:
- for item in self.groupnotification:
- if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
- if int(item.get("_widget_1743065201886")) == 1: # 是否启动短信功能
- payload_dict.update({"_widget_1735106258086": {"value": "是"}}) # DX:是否拥有
- break
- else:
- payload_dict.update({"_widget_1735106258086": {"value": "否"}}) # DX:是否拥有
- break
- except Exception as e:
- print(f"短信:Error finding customer service: {e}")
- try:
- for item in self.groupnotification:
- if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
- if int(item.get("_widget_1743065201889")) > 0: # 累计发送成功总人数
- payload_dict.update({"_widget_1735106258088": {"value": "是"}}) # DX:是否使用
- break
- else:
- payload_dict.update({"_widget_1735106258088": {"value": "否"}}) # DX:是否使用
- break
- except Exception as e:
- print(f"短信:Error finding customer service: {e}")
- NGV_data_id = None
- # 获取关联数据
- for NGV_Data in self.NGV_data_list:
- # NGV_Data = NGV_Data.get("data")
- if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
- NGV_data_id = NGV_Data.get("_id")
- print(NGV_data_id)
- try:
- png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
- except:
- png_url = ""
- print(png_url)
- if not NGV_data_id:
- print("未找到数据ID")
+ # 初始化默认值为"否"
+ payload_dict["_widget_1735107354650"] = {"value": "否"}
- distribution_date = datetime.datetime.now(datetime.timezone.utc)
- distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
+ # 检查每个键,如果有一个大于0,则更新为"是"并停止检查
+ for key in keys_to_check:
+ for item in self.Smart_detection:
+ if row["id_own_org"] == item.get("_widget_1735113110147"):
+ if int(item.get(key, 0)) > 0: # 使用get方法并提供默认值0防止键不存在的情况
+ payload_dict["_widget_1735107354650"]["value"] = "是"
+ break
- upload_key = None
- UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
- if png_url:
- save_dir = "sampleCloud" # 设置输出目录
+ # 近30天业务单量=0 则其它所有模块均不推荐
+ try:
+ for feature_module, feature_value in feature_dict.items(): # 模块
+ if row["bill_count_last_30_day"] == '0' and payload_dict[feature_value]["value"] == '△':
+ payload_dict.update({f"{feature_value}": {"value": "×"}})
+ except Exception as e:
+ error_task_logger.error(f"不开单识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-不开单识别", str(e))
- # 创建输出目录(如果不存在)
- import os
+ # 保单识别:从系统中抽取目标门店,针对门店抽取修改是否推荐
+ try:
+ if row["org_code"] in self.widget_list:
+ payload_dict.update({'_widget_1735004315746': {"value": "△"}})
+ except Exception as e:
+ error_task_logger.error(f"保单识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-保单识别", str(e))
- os.makedirs(save_dir, exist_ok=True)
+ # 私域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
+ try:
+ for item in self.private_domain:
+ if row["id_own_group"] == item.get("_widget_1742795002375"): # 公司id
+ if int(item.get("_widget_1742795002379")) > 0: # 上架商品数
+ payload_dict.update({"_widget_1735106258143": {"value": "是"}}) # DX:是否拥有
+ break
+ else:
+ payload_dict.update({"_widget_1735106258143": {"value": "否"}}) # DX:是否拥有
+ break
+ except Exception as e:
+ error_task_logger.error(f"小程序识别:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-小程序识别", str(e))
- save_path = fr'{save_dir}\png\{time.strftime("%Y%m%d%H%M%S", time.localtime())}.png'
+ try:
+ high_version = ['皇冠版', '至尊版', '尊享版', '旗舰版']
+ if row["saas_edition_fmt"] in high_version:
+ payload_dict.update({'_widget_1735106258141': {"value": "是"}}) # SYXCX:是否拥有
+ else:
+ payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"私域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-私域小程序", str(e))
- RenewServicesRevisit.download_url_content(png_url, save_path)
+ # 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
+ try:
+ for item in self.public_domain:
+ if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
+ if int(item.get("_widget_1742784257509")) == 1: # 发布商品数量
+ payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
+ break
+ else:
+ payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
+ break
+ except Exception as e:
+ error_task_logger.error(f"公域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-公域小程序", str(e))
- up_data = api_instance.get_upload_token(
- {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b9c63925cd404038a6b86",
- "transaction_id": UUid})
- upload_url = up_data.get("upload_url")
- upload_token = up_data.get("upload_token")
+ try:
+ if row["id_own_org"] in self.public_domain_list:
+ payload_dict.update({'_widget_1735106258112': {"value": "是"}}) # GYXCX:是否拥有
+ else:
+ payload_dict.update({'_widget_1735106258112': {"value": "否"}}) # GYXCX:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"公域小程序:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-公域小程序", str(e))
- upload_result = api_instance.upload_file(
- {"upload_url": upload_url, "upload_token": upload_token, "file_path": save_path})
- upload_key = upload_result.get("key")
+ # 异业合作:根据是否存在判断是否拥有,过滤条件 商品名称包含异业两个字
+ try:
+ if row["id_own_org"] in self.different_industries_list:
+ payload_dict.update({'_widget_1735107355618': {"value": "是"}}) # YYHZ:是否拥有
+ else:
+ payload_dict.update({'_widget_1735107355618': {"value": "否"}}) # YYHZ:是否拥有
+ except Exception as e:
+ error_task_logger.error(f"异业合作:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-异业合作", str(e))
- payload_dict.update({
- "_widget_1734590278279": {"value": row["group_name"]}, # 公司名称
- "_widget_1735112931760": {"value": row["id_own_group"]}, # 公司id
- "_widget_1735112931761": {"value": row["id_own_org"]}, # 门店id
- "_widget_1734590278281": {"value": row['org_name']}, # 门店名称
- "_widget_1734590278292": {"value": row["跟进阶段"]}, # 跟进阶段
- "_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
- "_widget_1742548684369": {"value": row['主要目的']}, # 主要目的
- "_widget_1734590278266": {"value": row['region_name']}, # 大区
- "_widget_1734590278285": {"value": row['branch_name']}, # 小区
- "_widget_1734590278284": {"value": row['province_name']}, # 省
- "_widget_1734590278283": {"value": row['city_name']}, # 市
- "_widget_1734590278282": {"value": row['area_name']}, # 区
- "_widget_1734590278278": {"value": row['saas_customer_type']}, # 门店分层
- "_widget_1734590278277": {"value": row['group_grade']}, # 公司等级
- "_widget_1734590278276": {"value": row['limit_user_type']}, # 限制账户类型
- "_widget_1734590278275": {"value": row['active_user_type']}, # 有效账户类型
- "_widget_1734590278274": {"value": row['saas_version']}, # ERP操作模式
- "_widget_1734590278273": {"value": row['saas_use_year']}, # 使用时长
- "_widget_1734590278272": {"value": row['org_stage']}, # 门店阶段
- "_widget_1734590278271": {"value": row['manage_model']}, # 经营模式
- "_widget_1734590278267": {"value": row['contacts']}, # 联系人
- "_widget_1734590278287": {"value": row['contact_mobile']}, # 联系手机号
- "_widget_1734590278286": {"value": row['saas_edition_fmt']}, # SaaS版本
- "_widget_1734590278280": {"value": row['org_code']}, # 门店编码
- # "_widget_1735287791875": {"value": row['salesmen']}, # 销售负责人
- "_widget_1735096489244": {"value": distribution_date}, # 派发时间
- "_widget_1742895342914": {"value": row['business_scope_fmt']}, # 经营范围
- "_widget_1742895342915": {"value": row['station_number']}, # 工位数
- "_widget_1742895342916": {"value": [upload_key]} # 门头照片
- })
+ # 短信:根据是否启动短信功能判断是否拥有,根据
+ try:
+ for item in self.groupnotification:
+ if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
+ if int(item.get("_widget_1743065201886")) == 1: # 是否启动短信功能
+ payload_dict.update({"_widget_1735106258086": {"value": "是"}}) # DX:是否拥有
+ break
+ else:
+ payload_dict.update({"_widget_1735106258086": {"value": "否"}}) # DX:是否拥有
+ break
+ except Exception as e:
+ error_task_logger.error(f"短信是否使用:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-短信是否使用", str(e))
- routine_follow_up_payload = {
- "api_key": "675b900991ad2491c69389ca",
- "entry_id": "675b9c63925cd404038a6b86",
- "is_start_workflow": "true",
- "data": payload_dict,
- "transaction_id": UUid
- }
+ try:
+ for item in self.groupnotification:
+ if row["id_own_group"] == item.get("_widget_1743065201885"): # 公司id
+ if int(item.get("_widget_1743065201889")) > 0: # 累计发送成功总人数
+ payload_dict.update({"_widget_1735106258088": {"value": "是"}}) # DX:是否使用
+ break
+ else:
+ payload_dict.update({"_widget_1735106258088": {"value": "否"}}) # DX:是否使用
+ break
+ except Exception as e:
+ error_task_logger.error(f"短信是否使用:Error finding customer service: {e}")
+ common_module.send_task_error(task_start_time, "手动添加日常回访-短信是否使用", str(e))
- print(routine_follow_up_payload)
+ NGV_data_id = None
+ # 获取关联数据
+ for NGV_Data in self.NGV_data_list:
+ # NGV_Data = NGV_Data.get("data")
+ if row["org_code"] == NGV_Data.get("_widget_1734062123071"): # 门店编码
+ NGV_data_id = NGV_Data.get("_id")
+ logger.info(f"关联数据数据id:{NGV_data_id}")
+ try:
+ png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
+ except:
+ png_url = ""
+ logger.info(f"关联数据图片:{png_url}")
+ if not NGV_data_id:
+ logger.warning("未找到数据ID")
- res = api_instance.data_batch_create(routine_follow_up_payload)
- logger.info(f"创建结果:{res}")
- time.sleep(1)
+ distribution_date = datetime.datetime.now(datetime.timezone.utc)
+ distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
- # print(res)
- except:
- pass
- common_module.send_task_status(task_start_time, "续约客户回访")
+ upload_key = None
+ UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
+ if png_url:
+ save_dir = "sampleCloud" # 设置输出目录
+
+ # 创建输出目录(如果不存在)
+ import os
+
+ os.makedirs(save_dir, exist_ok=True)
+
+ save_path = fr'{save_dir}\png\{time.strftime("%Y%m%d%H%M%S", time.localtime())}.png'
+
+ RenewServicesRevisit.download_url_content(png_url, save_path)
+ logger.info(f"已保存图片到 {save_path}。")
+
+ up_data = api_instance.get_upload_token(
+ {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b9c63925cd404038a6b86",
+ "transaction_id": UUid})
+ upload_url = up_data.get("upload_url")
+ upload_token = up_data.get("upload_token")
+
+ upload_result = api_instance.upload_file(
+ {"upload_url": upload_url, "upload_token": upload_token, "file_path": save_path})
+ upload_key = upload_result.get("key")
+ logger.info("已上传文件")
+
+ payload_dict.update({
+ "_widget_1734590278279": {"value": row["group_name"]}, # 公司名称
+ "_widget_1735112931760": {"value": row["id_own_group"]}, # 公司id
+ "_widget_1735112931761": {"value": row["id_own_org"]}, # 门店id
+ "_widget_1734590278281": {"value": row['org_name']}, # 门店名称
+ "_widget_1734590278292": {"value": row["跟进阶段"]}, # 跟进阶段
+ "_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
+ "_widget_1742548684369": {"value": row['主要目的']}, # 主要目的
+ "_widget_1734590278266": {"value": row['region_name']}, # 大区
+ "_widget_1734590278285": {"value": row['branch_name']}, # 小区
+ "_widget_1734590278284": {"value": row['province_name']}, # 省
+ "_widget_1734590278283": {"value": row['city_name']}, # 市
+ "_widget_1734590278282": {"value": row['area_name']}, # 区
+ "_widget_1734590278278": {"value": row['saas_customer_type']}, # 门店分层
+ "_widget_1734590278277": {"value": row['group_grade']}, # 公司等级
+ "_widget_1734590278276": {"value": row['limit_user_type']}, # 限制账户类型
+ "_widget_1734590278275": {"value": row['active_user_type']}, # 有效账户类型
+ "_widget_1734590278274": {"value": row['saas_version']}, # ERP操作模式
+ "_widget_1734590278273": {"value": row['saas_use_year']}, # 使用时长
+ "_widget_1734590278272": {"value": row['org_stage']}, # 门店阶段
+ "_widget_1734590278271": {"value": row['manage_model']}, # 经营模式
+ "_widget_1734590278267": {"value": row['contacts']}, # 联系人
+ "_widget_1734590278287": {"value": row['contact_mobile']}, # 联系手机号
+ "_widget_1734590278286": {"value": row['saas_edition_fmt']}, # SaaS版本
+ "_widget_1734590278280": {"value": row['org_code']}, # 门店编码
+ # "_widget_1735287791875": {"value": row['salesmen']}, # 销售负责人
+ "_widget_1735096489244": {"value": distribution_date}, # 派发时间
+ "_widget_1742895342914": {"value": row['business_scope_fmt']}, # 经营范围
+ "_widget_1742895342915": {"value": row['station_number']}, # 工位数
+ "_widget_1742895342916": {"value": [upload_key]} # 门头照片
+ })
+
+ routine_follow_up_payload = {
+ "api_key": "675b900991ad2491c69389ca",
+ "entry_id": "675b9c63925cd404038a6b86",
+ "is_start_workflow": "true",
+ "data": payload_dict,
+ "transaction_id": UUid
+ }
+
+ res = api_instance.data_batch_create(routine_follow_up_payload)
+ logger.info(f"创建结果:{res}")
+ time.sleep(1)
+
+ # print(res)
+ except:
+ pass
+ common_module.send_task_status(task_start_time, "续约客户回访")
+ logger.info("续约客户回访任务完成")
+ except Exception as e:
+ common_module.send_task_error(task_start_time, "续约客户回访", str(e))
+ error_task_logger.error(f"续约客户回访任务执行时发生异常: {e}")
if __name__ == '__main__':
diff --git a/back_ground_module/update_BI_CRM_info.py b/back_ground_module/update_BI_CRM_info.py
index 3aead36..2109dee 100644
--- a/back_ground_module/update_BI_CRM_info.py
+++ b/back_ground_module/update_BI_CRM_info.py
@@ -8,12 +8,20 @@ from dateutil.parser import parse
from back_ground_module import CommonModule
import numpy as np
from config import Config
+from log_config import configure_task_logger, configure_error_task_logger
common_module = CommonModule()
+# 获取已经配置好的常规日志记录器
+logger = configure_task_logger()
+
+# 获取已经配置好的错误任务日志记录器
+error_task_logger = configure_error_task_logger()
+
class CRMDataProcessor:
"""泰国CRM数据迁移到BI"""
+
def __init__(self):
"""
初始化CRM数据处理类
@@ -178,13 +186,6 @@ class CRMDataProcessor:
# 去掉前六列和后两列
df = df.iloc[:, 6:-2]
- # del df["creator"]
- # del df["createTime"]
- # del df["updateTime"]
- # del df["updater"]
- # del df["deleter"]
- # del df["deleteTime"]
-
# 生成URL
base_url = f"https://www.jiandaoyun.com/dashboard/app/{self.api_key}/form/{self.entry_id}/data/"
df['url'] = base_url + df['_id'].astype(str) + "/qr_link"
@@ -219,7 +220,7 @@ class CRMDataProcessor:
# 只保留映射后的列和URL字段
mapped_columns = list(self.id_to_name_mapping.values()) + ['url']
df = df[[col for col in mapped_columns if col in df.columns]]
- #df.replace([np.nan, None, r'^\s*$'], "", regex=True, inplace=True)
+ # df.replace([np.nan, None, r'^\s*$'], "", regex=True, inplace=True)
# 修改替换空值的实现方式
df = df.fillna("") # 先替换NaN和None
df = df.replace(r'^\s*$', "", regex=True) # 再替换空字符串
@@ -284,9 +285,11 @@ class CRMDataProcessor:
self.connect_db()
self.cursor.execute(f"TRUNCATE TABLE {table_name}")
self.connection.commit()
- print(f"成功清空表 {table_name} 中的所有数据")
+ logger.info(f"成功清空表 {table_name} 中的所有数据")
except Error as e:
- print(f"清空表时发生错误: {e}")
+ error_task_logger.error(f"清空表时发生错误: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "简道云海外项目CRM客户档案迁移BI", str(e))
if self.connection and self.connection.is_connected():
self.connection.rollback()
raise
@@ -319,48 +322,46 @@ class CRMDataProcessor:
records = [tuple(row) for row in df.values]
self.cursor.executemany(insert_query, records)
self.connection.commit()
- print(f"成功导入 {self.cursor.rowcount} 条记录到 {table_name} 表")
+
+ logger.info(f"成功导入 {self.cursor.rowcount} 条记录到 {table_name} 表")
except Error as e:
- print(f"导入数据时发生错误: {e}")
+ error_task_logger.error(f"导入数据时发生错误: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "简道云海外项目CRM客户档案迁移BI", str(e))
if self.connection and self.connection.is_connected():
self.connection.rollback()
raise
finally:
self.close_db()
- # # 批量插入数据
- # records = [tuple(None if pd.isna(x) else x for x in row) for row in df.values]
- # self.cursor.executemany(insert_query, records)
- # self.connection.commit()
- # print(f"成功导入 {self.cursor.rowcount} 条记录到 {table_name} 表")
- # except Error as e:
- # print(f"导入数据时发生错误: {e}")
- # raise
- # finally:
- # self.close_db()
-
-
def main(self):
"""运行完整的数据处理流程"""
table_name = "jiandaoyun_crm_customer_profile"
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+
try:
+ logger.info(f"开始处理任务")
# 获取数据
raw_data = self.fetch_crm_data()
+ logger.info("数据获取完成")
# 处理数据
processed_data = self.process_data(raw_data)
+ logger.info("数据处理完成")
# 清空表
self.clear_table(table_name)
+ logger.info("表清空完成")
# 导入数据
self.import_data(processed_data, table_name)
+ logger.info("数据导入完成")
- print("数据处理流程完成")
+ logger.info("数据处理流程完成")
except Exception as e:
- print(f"数据处理流程出错: {e}")
+ common_module.send_task_error(task_start_time, "简道云海外项目CRM客户档案迁移BI", str(e))
+ error_task_logger.error(f"任务简道云海外项目CRM客户档案迁移BI执行失败。")
raise
common_module.send_task_status(task_start_time, "简道云海外项目CRM客户档案迁移BI")
diff --git a/back_ground_module/update_ID_form.py b/back_ground_module/update_ID_form.py
index ba5ca20..4eb1019 100644
--- a/back_ground_module/update_ID_form.py
+++ b/back_ground_module/update_ID_form.py
@@ -18,8 +18,10 @@ error_task_logger = configure_error_task_logger()
common_module = CommonModule()
+
class update_ID_form:
"""更新简道云员工ID表"""
+
def __init__(self):
self.headers = {
'Authorization': Config.JIANDAOYUN_API_TOKEN, # 曹伟应用api测试 app_key
@@ -54,6 +56,8 @@ class update_ID_form:
return df1
except Exception as e:
error_task_logger.error(f"获取部门成员及ID表失败:{e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "简道云员工ID表更新", str(e))
return None
def get_existing_id_form(self):
@@ -65,6 +69,8 @@ class update_ID_form:
return df
except Exception as e:
error_task_logger.error(f"读取现有的ID表失败:{e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "简道云员工ID表更新", str(e))
return None
def delete_existing_data(self, df):
@@ -78,6 +84,8 @@ class update_ID_form:
logger.info("现有数据已成功删除")
except Exception as e:
error_task_logger.error(f"批量删除现有数据失败:{e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "简道云员工ID表更新", str(e))
def update_data(self, df1):
"""批量写入新数据"""
@@ -93,21 +101,27 @@ class update_ID_form:
logger.info("新数据已成功写入")
except Exception as e:
error_task_logger.error(f"批量写入新数据失败:{e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "简道云员工ID表更新", str(e))
def main(self):
"""主函数"""
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- logger.info("每日任务开始执行")
- df1 = self.get_department_members()
- if df1 is not None:
- df = self.get_existing_id_form()
- if df is not None:
- self.delete_existing_data(df)
- self.update_data(df1)
- logger.info("每日任务执行完成")
- common_module.send_task_status(task_start_time, "简道云员工ID表更新")
+ try:
+ logger.info("每日任务开始执行")
+ df1 = self.get_department_members()
+ if df1 is not None:
+ df = self.get_existing_id_form()
+ if df is not None:
+ self.delete_existing_data(df)
+ self.update_data(df1)
+ logger.info("每日任务执行完成")
+ common_module.send_task_status(task_start_time, "简道云员工ID表更新")
+ except Exception as e:
+ error_task_logger.error(f"简道云员工ID表更新任务执行失败:{e}")
+ common_module.send_task_error(task_start_time, "简道云员工ID表更新", str(e))
if __name__ == '__main__':
daily_task = update_ID_form()
- daily_task.main()
\ No newline at end of file
+ daily_task.main()
diff --git a/back_ground_module/update_NGV_data.py b/back_ground_module/update_NGV_data.py
index 587748d..c441727 100644
--- a/back_ground_module/update_NGV_data.py
+++ b/back_ground_module/update_NGV_data.py
@@ -4,7 +4,12 @@ import datetime
from config import Config
from api import API
from back_ground_module import CommonModule
+from log_config import configure_task_logger, configure_error_task_logger
+logger = configure_task_logger()
+
+# 获取已经配置好的错误任务日志记录器
+error_task_logger = configure_error_task_logger()
start_time = datetime.datetime.now()
api_instance = API()
common_module = CommonModule()
@@ -12,6 +17,7 @@ common_module = CommonModule()
class UpdateNGVData:
"""NGV数据每日新增"""
+
def __init__(self):
self.staff_id_list = None
self.field_mapping = {}
@@ -33,88 +39,91 @@ class UpdateNGVData:
return None
def main(self):
- self.load_all_data()
-
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- data_NGV_j = common_module.get_ngv_details(days_back=1)
- data_NGV_j1 = common_module.get_ngv_details(days_back=2)
+ try:
+ self.load_all_data()
+ logger.info(f"数据加载完成")
- # 找出在 data_NGV_j 中存在但在 data_NGV_j1 中不存在的 data_id
- unique_data_ids = data_NGV_j[~data_NGV_j['org_code'].isin(data_NGV_j1['org_code'])]
+ data_NGV_j = common_module.get_ngv_details(days_back=1)
+ data_NGV_j1 = common_module.get_ngv_details(days_back=2)
- # 创建一个新的 DataFrame 保存这些唯一的 data_id 及其对应的数据
- new_df = data_NGV_j[data_NGV_j['org_code'].isin(unique_data_ids['org_code'])]
+ # 找出在 data_NGV_j 中存在但在 data_NGV_j1 中不存在的 data_id
+ unique_data_ids = data_NGV_j[~data_NGV_j['org_code'].isin(data_NGV_j1['org_code'])]
- # 对 new_df 进行进一步的过滤,只保留 org_type 为 "一般" 的记录
- data_NGV_j = data_NGV_j[data_NGV_j['org_type'] == '一般']
- data_NGV_j1 = data_NGV_j1[data_NGV_j1['org_type'] == '一般']
- filtered_df = new_df[new_df['org_type'] == '一般']
+ # 创建一个新的 DataFrame 保存这些唯一的 data_id 及其对应的数据
+ new_df = data_NGV_j[data_NGV_j['org_code'].isin(unique_data_ids['org_code'])]
- # 日期字段转换为日期格式
- time_columns = ['date_fmt', 'saas_create_time', 'expiry_time', 'install_create_time', "last_end_date",
- "renew_date"]
- new_filtered_df = filtered_df.copy() # 复制df,以调整时间
- for col in time_columns:
- # 1. 转换为datetime类型(带错误处理)
- # 使用.loc安全赋值
- new_filtered_df[col] = pd.to_datetime(filtered_df[col], errors='coerce', utc=False)
+ # 对 new_df 进行进一步的过滤,只保留 org_type 为 "一般" 的记录
+ data_NGV_j = data_NGV_j[data_NGV_j['org_type'] == '一般']
+ data_NGV_j1 = data_NGV_j1[data_NGV_j1['org_type'] == '一般']
+ filtered_df = new_df[new_df['org_type'] == '一般']
- # 2. 优化后的时区转换(高效向量化操作)
- filtered_df[col + '_date'] = (
- new_filtered_df[col]
- # 本地化为北京时间(东八区)
- .dt.tz_localize('Asia/Shanghai', ambiguous='infer', nonexistent='NaT')
- # 转换为UTC时区
- .dt.tz_convert('UTC')
- # 格式化为ISO8601字符串
- .dt.strftime('%Y-%m-%dT%H:%M:%SZ')
- )
+ # 日期字段转换为日期格式
+ time_columns = ['date_fmt', 'saas_create_time', 'expiry_time', 'install_create_time', "last_end_date",
+ "renew_date"]
+ new_filtered_df = filtered_df.copy() # 复制df,以调整时间
+ for col in time_columns:
+ # 1. 转换为datetime类型(带错误处理)
+ # 使用.loc安全赋值
+ new_filtered_df[col] = pd.to_datetime(filtered_df[col], errors='coerce', utc=False)
- # 人员字段转换为人员字段
- staff_columns = ['area_manager', 'service_impl_principal', "service_salesmen","technician"]
- # 将员工列表转为DataFrame
- # 三重循环临时方案(确保可写入)
- for col in staff_columns:
- staff_ids = []
- for _, row in filtered_df.iterrows():
- matched = False
- for staff in self.staff_id_list:
- if str(staff['_widget_1734942794144']) == str(row[col]):
- staff_ids.append(staff['_widget_1734942794145'])
- matched = True
- break
- if not matched:
- staff_ids.append(None)
- filtered_df[col + "_staff_id"] = staff_ids
+ # 2. 优化后的时区转换(高效向量化操作)
+ filtered_df[col + '_date'] = (
+ new_filtered_df[col]
+ # 本地化为北京时间(东八区)
+ .dt.tz_localize('Asia/Shanghai', ambiguous='infer', nonexistent='NaT')
+ # 转换为UTC时区
+ .dt.tz_convert('UTC')
+ # 格式化为ISO8601字符串
+ .dt.strftime('%Y-%m-%dT%H:%M:%SZ')
+ )
+ logger.info(f"时间转换完成")
- # filtered_df.to_csv(r"D:\Idea Project\SaaS_V1.3\back_ground_module\output\NGV.csv")
+ # 人员字段转换为人员字段
+ staff_columns = ['area_manager', 'service_impl_principal', "service_salesmen", "technician"]
+ # 将员工列表转为DataFrame
+ # 三重循环临时方案(确保可写入)
+ for col in staff_columns:
+ staff_ids = []
+ for _, row in filtered_df.iterrows():
+ matched = False
+ for staff in self.staff_id_list:
+ if str(staff['_widget_1734942794144']) == str(row[col]):
+ staff_ids.append(staff['_widget_1734942794145'])
+ matched = True
+ break
+ if not matched:
+ staff_ids.append(None)
+ filtered_df[col + "_staff_id"] = staff_ids
+ logger.info(f"人员转换完成")
- # 生成包含所有行转换后的字典列表
- # all_data = [self.row_to_dict(row, self.field_mapping) for index, row in data_NGV_j1.iterrows()] # 前两天的全部数据
- # all_data = [self.row_to_dict(row, self.field_mapping) for index, row in data_NGV_j.iterrows()] # 前一天的全部数据
- all_data = [self.row_to_dict(row, self.field_mapping) for index, row in filtered_df.iterrows()] # 增量数据
+ # filtered_df.to_csv(r"D:\Idea Project\SaaS_V1.3\back_ground_module\output\NGV.csv")
- #
- data = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.NGV_TASKS_ENTRY_ID, "data_list": all_data}
+ # 生成包含所有行转换后的字典列表
+ # all_data = [self.row_to_dict(row, self.field_mapping) for index, row in data_NGV_j1.iterrows()] # 前两天的全部数据
+ # all_data = [self.row_to_dict(row, self.field_mapping) for index, row in data_NGV_j.iterrows()] # 前一天的全部数据
+ all_data = [self.row_to_dict(row, self.field_mapping) for index, row in filtered_df.iterrows()] # 增量数据
- result = api_instance.entry_data_batch_create(data)
- # result_str = str(result)
- # print(result_str[:500])
+ #
+ data = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.NGV_TASKS_ENTRY_ID, "data_list": all_data}
- # 保存到Excel文件
- # output_path = r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细1.xlsx'
- # filtered_df.to_excel(output_path, index=False)
- # data_NGV_j1.to_excel( r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细j1.xlsx', index=False)
- # data_NGV_j.to_excel( r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细j.xlsx', index=False)
- # new_df.to_excel(r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细ndf.xlsx', index=False)
+ result = api_instance.entry_data_batch_create(data)
+ logger.info(f"数据已推送:{result}")
+ # result_str = str(result)
+ # print(result_str[:500])
- end_time = datetime.datetime.now()
+ # 保存到Excel文件
+ # output_path = r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细1.xlsx'
+ # filtered_df.to_excel(output_path, index=False)
+ # data_NGV_j1.to_excel( r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细j1.xlsx', index=False)
+ # data_NGV_j.to_excel( r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细j.xlsx', index=False)
+ # new_df.to_excel(r'D:\Idea Project\F6+宜搭+其它(1)\new\文件输出\ngv明细ndf.xlsx', index=False)
- time_diff = end_time - start_time
-
- # 打印天数、秒数和微秒数
- print(f"执行时间: {time_diff.days} 天, {time_diff.seconds} 秒, {time_diff.microseconds} 微秒")
- common_module.send_task_status(task_start_time, "NGV新增数据")
+ common_module.send_task_status(task_start_time, "NGV新增数据")
+ logger.info(f"任务完成。")
+ except Exception as e:
+ error_task_logger.error(f"任务执行时发生异常: {e}")
+ common_module.send_task_error(task_start_time, "NGV新增数据", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
diff --git a/back_ground_module/update_all_NGV_data_daily.py b/back_ground_module/update_all_NGV_data_daily.py
index 5e80538..c3f7809 100644
--- a/back_ground_module/update_all_NGV_data_daily.py
+++ b/back_ground_module/update_all_NGV_data_daily.py
@@ -16,6 +16,13 @@ error_task_logger = configure_error_task_logger()
start_time = datetime.datetime.now()
api_instance = API()
common_module = CommonModule()
+# 保存为CSV文件
+output_dir = "output" # 设置输出目录
+
+# 创建输出目录(如果不存在)
+import os
+
+os.makedirs(output_dir, exist_ok=True)
class UpdateAllNGVDataDaily:
@@ -26,225 +33,221 @@ class UpdateAllNGVDataDaily:
self.fields()
def main(self):
- # 保存为CSV文件
- output_dir = "output" # 设置输出目录
-
- # 创建输出目录(如果不存在)
- import os
- os.makedirs(output_dir, exist_ok=True)
-
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # 获取NGV数据
- payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
- NGV_data_list = api_instance.entry_data_list(payload).get("data", [])
- jdy_NGV_data = pd.DataFrame(NGV_data_list)
+ try:
+ logger.info("开始执行任务:{}".format(task_start_time))
+ # 获取NGV数据
+ payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
+ NGV_data_list = api_instance.entry_data_list(payload).get("data", [])
+ jdy_NGV_data = pd.DataFrame(NGV_data_list)
- payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
- "entry_id": "6769204a1902c9341340a1bc",
- }
- staff_id = api_instance.entry_data_list(payload)
- staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
+ payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
+ "entry_id": "6769204a1902c9341340a1bc",
+ }
+ staff_id = api_instance.entry_data_list(payload)
+ staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
+ logger.info("已获取数据")
- # for i in range(1,2):
- data_NGV_j = common_module.get_ngv_details(days_back=1)
- data_NGV_j.to_csv(os.path.join(output_dir, f"data_NGV_j.csv"), index=False)
- data_NGV_j1 = common_module.get_ngv_details(days_back=2)
+ # for i in range(1,2):
+ data_NGV_j = common_module.get_ngv_details(days_back=1)
+ data_NGV_j.to_csv(os.path.join(output_dir, f"data_NGV_j.csv"), index=False)
+ data_NGV_j1 = common_module.get_ngv_details(days_back=2)
- # 对 data_NGV 进行进一步的过滤,只保留 org_type 为 "一般" 的记录
- data_NGV_j = data_NGV_j[data_NGV_j['org_type'] == '一般']
- data_NGV_j1 = data_NGV_j1[data_NGV_j1['org_type'] == '一般']
+ # 对 data_NGV 进行进一步的过滤,只保留 org_type 为 "一般" 的记录
+ data_NGV_j = data_NGV_j[data_NGV_j['org_type'] == '一般']
+ data_NGV_j1 = data_NGV_j1[data_NGV_j1['org_type'] == '一般']
- # 去除不需要的列
- columns_to_remove = {'date_id', 'date_fmt', 'pt', 'etl_time'}
+ # 去除不需要的列
+ columns_to_remove = {'date_id', 'date_fmt', 'pt', 'etl_time'}
- # 获取所有列名并计算要保留的列
- columns_to_keep_df1 = list(set(data_NGV_j.columns) - columns_to_remove)
- columns_to_keep_df2 = list(set(data_NGV_j1.columns) - columns_to_remove)
+ # 获取所有列名并计算要保留的列
+ columns_to_keep_df1 = list(set(data_NGV_j.columns) - columns_to_remove)
+ columns_to_keep_df2 = list(set(data_NGV_j1.columns) - columns_to_remove)
- # 过滤DataFrame以去除指定列
- df1_filtered = data_NGV_j[columns_to_keep_df1]
- df2_filtered = data_NGV_j1[columns_to_keep_df2]
+ # 过滤DataFrame以去除指定列
+ df1_filtered = data_NGV_j[columns_to_keep_df1]
+ df2_filtered = data_NGV_j1[columns_to_keep_df2]
- # 设置唯一标识列作为索引
- df1_set_index = df1_filtered.set_index('id_own_org')
- df2_set_index = df2_filtered.set_index('id_own_org')
+ # 设置唯一标识列作为索引
+ df1_set_index = df1_filtered.set_index('id_own_org')
+ df2_set_index = df2_filtered.set_index('id_own_org')
- df1_set_index = df1_set_index.astype(str).replace(['nan', 'None'], '', ).fillna("")
- df2_set_index = df2_set_index.astype(str).replace(['nan', 'None'], '', ).fillna("")
+ df1_set_index = df1_set_index.astype(str).replace(['nan', 'None'], '', ).fillna("")
+ df2_set_index = df2_set_index.astype(str).replace(['nan', 'None'], '', ).fillna("")
- # 找到两个DataFrame共有的索引
- common_index = df1_set_index.index.intersection(df2_set_index.index)
+ # 找到两个DataFrame共有的索引
+ common_index = df1_set_index.index.intersection(df2_set_index.index)
- # 使用共同的索引来重新索引两个DataFrame
- df1_common = df1_set_index.reindex(common_index).fillna('')
- df2_common = df2_set_index.reindex(common_index).fillna('')
+ # 使用共同的索引来重新索引两个DataFrame
+ df1_common = df1_set_index.reindex(common_index).fillna('')
+ df2_common = df2_set_index.reindex(common_index).fillna('')
- # 确保两个DataFrame有相同的列顺序
- common_columns = df1_common.columns.intersection(df2_common.columns)
- df1_common = df1_common[common_columns]
- df2_common = df2_common[common_columns]
+ # 确保两个DataFrame有相同的列顺序
+ common_columns = df1_common.columns.intersection(df2_common.columns)
+ df1_common = df1_common[common_columns]
+ df2_common = df2_common[common_columns]
- # 比较两个DataFrame的内容
- comparison_column = 'match_status'
+ # 比较两个DataFrame的内容
+ comparison_column = 'match_status'
- # 创建一个布尔Series,指示每一行是否完全相同
- matches = (df1_common == df2_common).all(axis=1)
+ # 创建一个布尔Series,指示每一行是否完全相同
+ matches = (df1_common == df2_common).all(axis=1)
- # 添加新列到第一个DataFrame,标记是否匹配
- df1_common[comparison_column] = matches.map({True: '一致', False: '不一致'})
- # df1_common.to_csv(os.path.join(output_dir, f"df1_common.csv"))
+ # 添加新列到第一个DataFrame,标记是否匹配
+ df1_common[comparison_column] = matches.map({True: '一致', False: '不一致'})
+ # df1_common.to_csv(os.path.join(output_dir, f"df1_common.csv"))
- # 如果需要也可以添加到第二个DataFrame(这里假设只需要处理df1_common)
- # df2_common[comparison_column] = matches.map({True: '一致', False: '不一致'})
+ # 如果需要也可以添加到第二个DataFrame(这里假设只需要处理df1_common)
+ # df2_common[comparison_column] = matches.map({True: '一致', False: '不一致'})
- # 提取只在一个DataFrame中存在的索引对应的行
- df1_only_index = df1_set_index.index.difference(df2_set_index.index)
- df2_only_index = df2_set_index.index.difference(df1_set_index.index)
+ # 提取只在一个DataFrame中存在的索引对应的行
+ df1_only_index = df1_set_index.index.difference(df2_set_index.index)
+ df2_only_index = df2_set_index.index.difference(df1_set_index.index)
- df1_only_rows = df1_set_index.loc[df1_only_index].copy()
- df2_only_rows = df2_set_index.loc[df2_only_index].copy()
+ df1_only_rows = df1_set_index.loc[df1_only_index].copy()
+ df2_only_rows = df2_set_index.loc[df2_only_index].copy()
- # 保存匹配结果
- # df1_common.to_csv(os.path.join(output_dir, 'matched_results.csv'), index_label='id_own_org')
+ # 保存匹配结果
+ # df1_common.to_csv(os.path.join(output_dir, 'matched_results.csv'), index_label='id_own_org')
- # 保存仅在df1中的行
- # df1_only_rows.to_csv(os.path.join(output_dir, 'df1_only_rows.csv'), index_label='id_own_org')
+ # 保存仅在df1中的行
+ # df1_only_rows.to_csv(os.path.join(output_dir, 'df1_only_rows.csv'), index_label='id_own_org')
- # 保存仅在df2中的行
- # df2_only_rows.to_csv(os.path.join(output_dir, 'df2_only_rows.csv'), index_label='id_own_org')
- # data_NGV_j.to_csv(os.path.join(output_dir, 'data_NGV_j.csv'), index_label='id_own_org')
- # data_NGV_j1.to_csv(os.path.join(output_dir, 'data_NGV_j1.csv'), index_label='id_own_org')
- # jdy_NGV_data.to_csv(os.path.join(output_dir, 'jdy_NGV_data.csv'), index_label='id_own_org')
+ # 保存仅在df2中的行
+ # df2_only_rows.to_csv(os.path.join(output_dir, 'df2_only_rows.csv'), index_label='id_own_org')
+ # data_NGV_j.to_csv(os.path.join(output_dir, 'data_NGV_j.csv'), index_label='id_own_org')
+ # data_NGV_j1.to_csv(os.path.join(output_dir, 'data_NGV_j1.csv'), index_label='id_own_org')
+ # jdy_NGV_data.to_csv(os.path.join(output_dir, 'jdy_NGV_data.csv'), index_label='id_own_org')
- # print(f"\nCSV文件已保存到目录: {output_dir}")
+ # print(f"\nCSV文件已保存到目录: {output_dir}")
- temp_jdy_NGV_data = jdy_NGV_data.copy()
+ temp_jdy_NGV_data = jdy_NGV_data.copy()
- # temp_jdy_NGV_data.to_csv(os.path.join(output_dir, 'jdy_NGV_data.csv'), index=False)
- temp_jdy_NGV_data.reset_index(inplace=True) # 如果 '门店id' 是索引,则先将其转换为普通列
- # temp_jdy_NGV_data.to_csv(os.path.join(output_dir, 'jdy_NGV_data1.csv'), index=False)
- if '_widget_1734062123069' not in temp_jdy_NGV_data.columns:
- print("列 '门店id' 不存在")
- temp_jdy_NGV_data.rename(columns={'_widget_1734062123069': 'id_own_org'}, inplace=True)
- temp_jdy_NGV_data.set_index('id_own_org', inplace=True)
+ # temp_jdy_NGV_data.to_csv(os.path.join(output_dir, 'jdy_NGV_data.csv'), index=False)
+ temp_jdy_NGV_data.reset_index(inplace=True) # 如果 '门店id' 是索引,则先将其转换为普通列
+ # temp_jdy_NGV_data.to_csv(os.path.join(output_dir, 'jdy_NGV_data1.csv'), index=False)
+ if '_widget_1734062123069' not in temp_jdy_NGV_data.columns:
+ error_task_logger.error("列 '门店id' 不存在")
+ temp_jdy_NGV_data.rename(columns={'_widget_1734062123069': 'id_own_org'}, inplace=True)
+ temp_jdy_NGV_data.set_index('id_own_org', inplace=True)
- # 如果简道云存在,NGV不存在则标记NGV已删除
- # 找出在 temp_jdy_NGV_data 中存在,但在 df1_common 中不存在的索引
- ids_in_jdy_not_in_df1 = temp_jdy_NGV_data.index[~temp_jdy_NGV_data.index.isin(df1_common.index)]
- # 提取这些行,形成新的 DataFrame
- only_in_temp_jdy = temp_jdy_NGV_data.loc[ids_in_jdy_not_in_df1]
- # 对数据源已经去掉的门店进行标记
- for index, only_row in only_in_temp_jdy.iterrows():
- result = {}
- if '_id' in only_in_temp_jdy.columns:
- _id_value = str(only_row['_id']) if not pd.isna(only_row['_id']) else None
- result["_id"] = _id_value
+ # 如果简道云存在,NGV不存在则标记NGV已删除
+ # 找出在 temp_jdy_NGV_data 中存在,但在 df1_common 中不存在的索引
+ ids_in_jdy_not_in_df1 = temp_jdy_NGV_data.index[~temp_jdy_NGV_data.index.isin(df1_common.index)]
+ # 提取这些行,形成新的 DataFrame
+ only_in_temp_jdy = temp_jdy_NGV_data.loc[ids_in_jdy_not_in_df1]
+ # 对数据源已经去掉的门店进行标记
+ for index, only_row in only_in_temp_jdy.iterrows():
+ result = {}
+ if '_id' in only_in_temp_jdy.columns:
+ _id_value = str(only_row['_id']) if not pd.isna(only_row['_id']) else None
+ result["_id"] = _id_value
- if result["_id"]:
- data = {
- 'api_key': Config.SaaS_Tasks_APP_ID,
- 'entry_id': Config.NGV_TASKS_ENTRY_ID,
- "data_id": result["_id"],
- "data": {"_widget_1754285499851": {"value": "已删除"}}
- }
+ if result["_id"]:
+ data = {
+ 'api_key': Config.SaaS_Tasks_APP_ID,
+ 'entry_id': Config.NGV_TASKS_ENTRY_ID,
+ "data_id": result["_id"],
+ "data": {"_widget_1754285499851": {"value": "已删除"}}
+ }
- api_instance.entry_data_update(data=data, max_retries=20)
+ api_instance.entry_data_update(data=data, max_retries=20)
- # 简道云与ngv不一致的数据做关联
- df1_common = df1_common.join(temp_jdy_NGV_data["_id"], how='left')
- df1_common = df1_common[df1_common['match_status'] == '不一致']
+ # 简道云与ngv不一致的数据做关联
+ df1_common = df1_common.join(temp_jdy_NGV_data["_id"], how='left')
+ df1_common = df1_common[df1_common['match_status'] == '不一致']
- # 日期字段转换为日期格式
- time_columns = ['saas_create_time', 'expiry_time', 'install_create_time', "last_end_date",
- "renew_date"]
- new_filtered_df = df1_common.copy() # 复制df,以调整时间
- for col in time_columns:
- # 1. 转换为datetime类型(带错误处理)
- # 使用.loc安全赋值
- new_filtered_df[col] = pd.to_datetime(df1_common[col], errors='coerce', utc=False)
+ # 日期字段转换为日期格式
+ time_columns = ['saas_create_time', 'expiry_time', 'install_create_time', "last_end_date",
+ "renew_date"]
+ new_filtered_df = df1_common.copy() # 复制df,以调整时间
+ for col in time_columns:
+ # 1. 转换为datetime类型(带错误处理)
+ # 使用.loc安全赋值
+ new_filtered_df[col] = pd.to_datetime(df1_common[col], errors='coerce', utc=False)
- # 2. 优化后的时区转换(高效向量化操作)
- df1_common[col + '_date'] = (
- new_filtered_df[col]
- # 本地化为北京时间(东八区)
- .dt.tz_localize('Asia/Shanghai', ambiguous='infer', nonexistent='NaT')
- # 转换为UTC时区
- .dt.tz_convert('UTC')
- # 格式化为ISO8601字符串
- .dt.strftime('%Y-%m-%dT%H:%M:%SZ')
- )
+ # 2. 优化后的时区转换(高效向量化操作)
+ df1_common[col + '_date'] = (
+ new_filtered_df[col]
+ # 本地化为北京时间(东八区)
+ .dt.tz_localize('Asia/Shanghai', ambiguous='infer', nonexistent='NaT')
+ # 转换为UTC时区
+ .dt.tz_convert('UTC')
+ # 格式化为ISO8601字符串
+ .dt.strftime('%Y-%m-%dT%H:%M:%SZ')
+ )
+ logger.info("日期已转换为UTC格式")
- # 人员字段转换为人员字段
- staff_columns = ['area_manager', 'service_impl_principal', "service_salesmen", "technician"]
- # 将员工列表转为DataFrame
- # 三重循环临时方案(确保可写入)
- for col in staff_columns:
- staff_ids = []
- for _, row in df1_common.iterrows():
- matched = False
- for staff in staff_id_list:
- if str(staff['_widget_1734942794144']) == str(row[col]):
- staff_ids.append(staff['_widget_1734942794145'])
- matched = True
- break
- if not matched:
- staff_ids.append(None)
- df1_common[col + "_staff_id"] = staff_ids
+ # 人员字段转换为人员字段
+ staff_columns = ['area_manager', 'service_impl_principal', "service_salesmen", "technician"]
+ # 将员工列表转为DataFrame
+ # 三重循环临时方案(确保可写入)
+ for col in staff_columns:
+ staff_ids = []
+ for _, row in df1_common.iterrows():
+ matched = False
+ for staff in staff_id_list:
+ if str(staff['_widget_1734942794144']) == str(row[col]):
+ staff_ids.append(staff['_widget_1734942794145'])
+ matched = True
+ break
+ if not matched:
+ staff_ids.append(None)
+ df1_common[col + "_staff_id"] = staff_ids
+ logger.info("人员字段已替换")
- # 并发请求
- futures = []
- all_data = []
+ # 并发请求
+ futures = []
+ all_data = []
+ logger.info(f"今日更新数据量为:{len(df1_common)}条")
- for idx, row in df1_common.iterrows():
- result = {}
- data_dict = {}
+ for idx, row in df1_common.iterrows():
+ result = {}
+ data_dict = {}
- # 根据 field_mapping 进行字段替换
- for col_name, widget_id in self.field_mapping.items():
- if col_name in df1_common.columns:
- value = row[col_name]
- clean_value = None if pd.isna(value) else value
- data_dict[widget_id] = {"value": clean_value}
+ # 根据 field_mapping 进行字段替换
+ for col_name, widget_id in self.field_mapping.items():
+ if col_name in df1_common.columns:
+ value = row[col_name]
+ clean_value = None if pd.isna(value) else value
+ data_dict[widget_id] = {"value": clean_value}
- # 单独处理 _id 列,并将其转换为字符串
- if '_id' in df1_common.columns:
- _id_value = str(row['_id']) if not pd.isna(row['_id']) else None
- result["_id"] = _id_value
+ # 单独处理 _id 列,并将其转换为字符串
+ if '_id' in df1_common.columns:
+ _id_value = str(row['_id']) if not pd.isna(row['_id']) else None
+ result["_id"] = _id_value
- # 组装最终结果
- if result["_id"]:
- data = {
- 'api_key': Config.SaaS_Tasks_APP_ID,
- 'entry_id': Config.NGV_TASKS_ENTRY_ID,
- "data_id": result["_id"],
- "data": data_dict
- }
+ # 组装最终结果
+ if result["_id"]:
+ data = {
+ 'api_key': Config.SaaS_Tasks_APP_ID,
+ 'entry_id': Config.NGV_TASKS_ENTRY_ID,
+ "data_id": result["_id"],
+ "data": data_dict
+ }
- api_instance.entry_data_update(data=data, max_retries=20)
- else:
- # continue
- data1 = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.NGV_TASKS_ENTRY_ID,
- "data": data_dict}
- api_instance.data_batch_create(data=data1, max_retries=20)
+ api_instance.entry_data_update(data=data, max_retries=20)
+ else:
+ # continue
+ data1 = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.NGV_TASKS_ENTRY_ID,
+ "data": data_dict}
+ res = api_instance.data_batch_create(data=data1, max_retries=20)
+ logger.info(f"补派数据:{res}")
+ # all_data.append(data_dict)
- # all_data.append(data_dict)
+ # 收集所有结果
+ for future in concurrent.futures.as_completed(futures):
+ try:
+ result = future.result()
+ logger.info(f"所有请求结果:{result}")
+ except Exception as exc:
+ error_task_logger.error(f"请求发生异常: {exc}")
- # 收集所有结果
- for future in concurrent.futures.as_completed(futures):
- try:
- result = future.result()
- print("请求结果:", result)
- except Exception as exc:
- print(f"请求发生异常: {exc}")
-
- end_time = datetime.datetime.now()
- # df11 = pd.DataFrame(all_data)
- # df11.to_csv(f"all_data.csv")
- time_diff = end_time - start_time
-
- # 打印天数、秒数和微秒数
- print(f"执行时间: {time_diff.days} 天, {time_diff.seconds} 秒, {time_diff.microseconds} 微秒")
- common_module.send_task_status(task_start_time, "NGV更新数据")
+ common_module.send_task_status(task_start_time, "NGV更新数据")
+ logger.info("NGV更新数据任务已完成。")
+ except Exception as e:
+ error_task_logger.error(f"NGV更新数据执行时发生异常: {e}")
+ common_module.send_task_error(task_start_time, "NGV更新数据", str(e))
@staticmethod
def row_to_dict(row, field_mapping):
diff --git a/back_ground_module/update_denominator_reporting_adjustment_to_bi.py b/back_ground_module/update_denominator_reporting_adjustment_to_bi.py
index cec580a..3806a9c 100644
--- a/back_ground_module/update_denominator_reporting_adjustment_to_bi.py
+++ b/back_ground_module/update_denominator_reporting_adjustment_to_bi.py
@@ -1,16 +1,11 @@
import mysql.connector
-from mysql.connector import Error
import numpy as np
-import pandas as pd
from yd_api import YDAPI
from api import API
import pandas as pd
-from tqdm import tqdm
-import time
-from datetime import datetime, timedelta
+from datetime import datetime
from config import Config
from back_ground_module import CommonModule
-import logging
from log_config import configure_task_logger, configure_error_task_logger
import mysql.connector
from mysql.connector import Error
@@ -33,11 +28,11 @@ FORMID = "FORM-WV866IC119W8BZC7AKHAR7VT3FI52W4Q1VBFLD1" # FPO需求提交
appType = "APP_UYZ0KG6L0CCNV80GZ66O" # F6客户服务
systemToken = "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2" # 密钥
BASE_URL = "https://f6car.aliwork.com" # 基础URL
-print(TOKEN)
DB_CONFIG = Config.HS_DB_Config
-# 数据库配置
+# 数据库配置
+
class DenominatorReportingAdjustment:
"""分母报备调整"""
@@ -45,7 +40,6 @@ class DenominatorReportingAdjustment:
def __init__(self):
self.structures = None
self.denominator_data_list = None
-
self.field_map = {
"门店编码": "textField_pl5p5a3",
"门店名称": "textField_fcl5xg6",
@@ -77,7 +71,6 @@ class DenominatorReportingAdjustment:
denominator_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=1, n=100,
appType=appType, systemToken=systemToken)
self.denominator_data_list = []
- print(denominator_data)
PAGES_two = denominator_data.get('totalCount') // 100 + 1
parentheses_pattern = re.compile(r'$[^)]*$')
@@ -89,7 +82,8 @@ class DenominatorReportingAdjustment:
# Transform the keys using field_map
transformed_data = {}
for field_key in ['employeeField_mca5shp1', 'employeeField_mca5shp0']:
- if field_key in form_data and isinstance(form_data[field_key], list) and len(form_data[field_key]) > 0:
+ if field_key in form_data and isinstance(form_data[field_key], list) and len(
+ form_data[field_key]) > 0:
# 取第一个元素
raw_value = form_data[field_key][0]
# 去除括号及其中的内容
@@ -108,10 +102,9 @@ class DenominatorReportingAdjustment:
# continue
self.denominator_data_list.append(transformed_data)
-
-
def execute_sql(self, sql, params=None, fetch=False, many=False):
"""执行SQL语句"""
+ global cursor
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
@@ -123,7 +116,7 @@ class DenominatorReportingAdjustment:
conn.commit()
return cursor.fetchall() if fetch else cursor
except Error as e:
- print(f"执行失败: {sql}\n错误: {e}")
+ error_task_logger.error(f"执行失败: {sql}\n错误: {e}")
if conn: conn.rollback()
return None
finally:
@@ -153,10 +146,9 @@ class DenominatorReportingAdjustment:
# 保留 DataFrame 中与数据库列名匹配的列
filtered_df = df[df.columns.intersection(db_columns)]
-
# 如果没有匹配的列,直接返回
if filtered_df.empty:
- print("DataFrame 中没有与数据库表结构匹配的列。")
+ logger.warning("DataFrame 中没有与数据库表结构匹配的列。")
return
# 筛选列之后,插入前处理 dict 类型
@@ -167,7 +159,6 @@ class DenominatorReportingAdjustment:
lambda x: json.dumps(x, ensure_ascii=False) if x is not None else x
)
-
# 构建插入语句
placeholders = ', '.join(['%s'] * len(filtered_df.columns))
# 使用反引号避免特殊列明
@@ -178,12 +169,14 @@ class DenominatorReportingAdjustment:
for _, row in filtered_df.iterrows():
cursor.execute(insert_sql, tuple(row))
-
connection.commit()
- print(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
+ logger.info(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
except Exception as e:
- print("写入数据库时发生错误:", e)
+ error_task_logger.error(f"写入数据时发生错误: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "分母报备调整", str(e))
+
connection.rollback()
finally:
cursor.close()
@@ -192,31 +185,37 @@ class DenominatorReportingAdjustment:
def clear_table(self):
"""清空表数据"""
if self.execute_sql("TRUNCATE TABLE f6_denominator_adjustment"):
- print("✅ 成功清空表数据")
+ logger.info("✅ 清空表数据成功")
def main(self):
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # step1:获取宜搭数据
- self.get_yida_data()
+ try:
+ # step1:获取宜搭数据
+ self.get_yida_data()
+ logger.info("✅ 获取宜搭数据成功")
- df = pd.DataFrame(self.denominator_data_list)
- df['开户日期'] = df['开户日期'].astype('Int64')
- df['开户日期'] = pd.to_datetime(df['开户日期'], unit='ms')
+ df = pd.DataFrame(self.denominator_data_list)
+ df['开户日期'] = df['开户日期'].astype('Int64')
+ df['开户日期'] = pd.to_datetime(df['开户日期'], unit='ms')
- df['结束时间'] = df['结束时间'].astype('Int64')
- df['结束时间'] = pd.to_datetime(df['结束时间'], unit='ms')
+ df['结束时间'] = df['结束时间'].astype('Int64')
+ df['结束时间'] = pd.to_datetime(df['结束时间'], unit='ms')
- df['开始时间'] = df['开始时间'].astype('Int64')
- df['开始时间'] = pd.to_datetime(df['开始时间'], unit='ms')
+ df['开始时间'] = df['开始时间'].astype('Int64')
+ df['开始时间'] = pd.to_datetime(df['开始时间'], unit='ms')
+ # step2:清空BI数据表
+ self.clear_table()
+ logger.info("✅ 清空表数据成功")
- # step2:清空BI数据表
- self.clear_table()
+ # # step3:写入BI数据库
+ self.write_to_bi(df)
+ logger.info("✅ 写入BI数据库成功")
- # # step3:写入BI数据库
- self.write_to_bi(df)
-
- common_module.send_task_status(task_start_time, "分母报备调整")
+ common_module.send_task_status(task_start_time, "分母报备调整")
+ except Exception as e:
+ error_task_logger.error("分母报备调整失败")
+ common_module.send_task_error(task_start_time, "分母报备调整", str(e))
if __name__ == '__main__':
diff --git a/back_ground_module/update_email_to_store_daily_use.py b/back_ground_module/update_email_to_store_daily_use.py
index cfdbed3..10ced72 100644
--- a/back_ground_module/update_email_to_store_daily_use.py
+++ b/back_ground_module/update_email_to_store_daily_use.py
@@ -1,7 +1,5 @@
import os
import poplib
-import time
-import pandas as pd
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
@@ -12,26 +10,29 @@ from back_ground_module import CommonModule
import pandas as pd
import pymysql
from pymysql import Error
+from log_config import configure_task_logger, configure_error_task_logger
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
api_instance = API()
common_module = CommonModule()
class EmailProcessor:
"""泰国CRM每日邮件写入简道云与BI"""
+
def __init__(self):
# 配置信息
self.user_email_address = 'caowei@f6car.cn'
self.user_password = 'Cw@340826'
self.pop_server_host = 'pop.qiye.aliyun.com'
- self.pop_server_port = '995'
+ self.pop_server_port = 995
self.send_name = "f6car"
self.send_addr = 'noreplay@notice.f6car.com'
# 创建输出目录(如果不存在)
output_dir = "email"
os.makedirs(output_dir, exist_ok=True)
- nowtime = datetime.now().strftime("%Y%m%d%H%M%S")
self.write_path = os.path.join(output_dir, f'email_data.xlsx')
@@ -47,7 +48,6 @@ class EmailProcessor:
"指标类型": "_widget_1742091963880",
"指标值": "_widget_1742091963882",
"指标子类型": "_widget_1742091963881",
- "指标值": "_widget_1742091963882"
}
def connect_email_by_pop3(self):
@@ -120,7 +120,7 @@ class EmailProcessor:
# 打印邮件接收时间
mail_time_str = datetime.strftime(mail_datetime, '%Y-%m-%d %H:%M:%S')
- print(f"邮件接收时间: {mail_time_str}")
+ logger.info(f"邮件接收时间: {mail_time_str}")
# 处理邮件内容
self.parser_content(msg, 0)
@@ -134,7 +134,6 @@ class EmailProcessor:
email_server.quit()
def parser_content(self, msg, indent):
- print("邮件处理")
if indent == 0:
self.parser_email_header(msg)
@@ -143,7 +142,6 @@ class EmailProcessor:
name, charset = decode_header(hdr)[0]
if charset:
name = name.decode(charset)
- print(f'发件人姓名: {name}, 发件人邮箱: {addr}')
if name == self.send_name:
# 下载附件
@@ -157,9 +155,9 @@ class EmailProcessor:
try:
with open(self.write_path, 'wb') as att_file:
att_file.write(data)
- print(f"附件保存成功: {self.write_path}+{filename}")
+ logger.info(f"附件保存成功: {self.write_path}+{filename}")
except Exception as e:
- print(f"附件保存失败: {str(e)}")
+ error_task_logger.error(f"保存附件时出错: {e}")
if msg.is_multipart():
parts = msg.get_payload()
@@ -173,7 +171,7 @@ class EmailProcessor:
charset = self.guess_charset(msg)
if charset:
content = content.decode(charset)
- print(f"{' ' * indent}邮件内容: {content}")
+ logger.info(f"邮件内容: {content}")
def parser_email_header(self, msg):
# 解析邮件主题
@@ -181,21 +179,22 @@ class EmailProcessor:
value, charset = decode_header(subject)[0]
if charset:
value = value.decode(charset)
- print(f'邮件主题: {value}')
+
# 解析发件人信息
hdr, addr = parseaddr(msg['From'])
- name, charset = decode_header(hdr)[0]
+ name1, charset = decode_header(hdr)[0]
if charset:
- name = name.decode(charset)
- print(f'发件人姓名: {name}, 发件人邮箱: {addr}')
+ name1 = name1.decode(charset)
+
# 解析收件人信息
hdr, addr = parseaddr(msg['To'])
name, charset = decode_header(hdr)[0]
if charset:
name = name.decode(charset)
- print(f'收件人姓名: {name}, 收件人邮箱: {addr}')
+ logger.info(f"邮件主题: {value}, 发件人: {name1}, 收件人: {name}")
+
@staticmethod
def decode_str(s):
@@ -229,6 +228,7 @@ class EmailProcessor:
mail_datetime = datetime.strptime(mail_datetime, ft)
return mail_datetime
except:
+ error_task_logger.error(f"邮件时间格式解析错误: {mail_datetime}")
pass
raise Exception("邮件时间格式解析错误")
@@ -244,8 +244,7 @@ class EmailProcessor:
return result
def update_email(self):
- # try:
- print(self.write_path)
+ logger.info("开始处理邮件数据")
email_df = pd.read_excel(self.write_path, sheet_name="Sheet0")
print(email_df.head())
@@ -269,6 +268,7 @@ class EmailProcessor:
def up_to_BI(self, df):
# 连接信息
+ global connection
HS_DB_Config = Config.HS_DB_Config
table_name = "thailand_store_data_email"
@@ -282,7 +282,6 @@ class EmailProcessor:
charset='utf8mb4',
)
- print(f"成功连接 {HS_DB_Config["database"]}")
with connection.cursor() as cursor:
# 处理数据
@@ -298,10 +297,12 @@ class EmailProcessor:
cursor.executemany(insert_query, records)
connection.commit()
- print(f"成功导入 {cursor.rowcount} 条记录到 {table_name} 表")
+ logger.info(f"成功导入 {cursor.rowcount} 条记录到 {table_name} 表")
except Error as e:
- print(f"数据库操作出错: {e}")
+ error_task_logger.error(f"数据库写入数据时发生异常: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "海外邮件推送", str(e))
if connection:
connection.rollback()
finally:
@@ -312,11 +313,16 @@ class EmailProcessor:
def main(cls):
"""邮件处理器的主入口点"""
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- processor = cls()
- processor.connect_email_by_pop3()
- email_df = processor.update_email()
- processor.up_to_BI(email_df) # 发送到BI
- common_module.send_task_status(task_start_time, "海外邮件推送")
+ try:
+ processor = cls()
+ processor.connect_email_by_pop3()
+ logger.info("邮件获取完成")
+ email_df = processor.update_email()
+ processor.up_to_BI(email_df) # 发送到BI
+ common_module.send_task_status(task_start_time, "海外邮件推送")
+ except Exception as e:
+ common_module.send_task_error(task_start_time, "海外邮件推送", "失败")
+ error_task_logger.error(f"任务执行时发生异常: {e}")
if __name__ == "__main__":
diff --git a/back_ground_module/update_molecule_reporting_adjustment_to_bi.py b/back_ground_module/update_molecule_reporting_adjustment_to_bi.py
index c7a33d2..0edd919 100644
--- a/back_ground_module/update_molecule_reporting_adjustment_to_bi.py
+++ b/back_ground_module/update_molecule_reporting_adjustment_to_bi.py
@@ -84,14 +84,13 @@ class MoleculeReportingAdjustment:
for field_id, value in form_data.items():
# Find the display name in field_map
for display_name, id_in_map in self.field_map.items():
- if id_in_map == field_id :
+ if id_in_map == field_id:
transformed_data[display_name] = value
break
# if transformed_data.get("是否上传衡石") == "否" or transformed_data.get("是否上传衡石") is None:
# continue
self.molecule_data_list.append(transformed_data)
-
def execute_sql(self, sql, params=None, fetch=False, many=False):
"""执行SQL语句"""
conn = None
@@ -105,7 +104,10 @@ class MoleculeReportingAdjustment:
conn.commit()
return cursor.fetchall() if fetch else cursor
except Error as e:
- print(f"执行失败: {sql}\n错误: {e}")
+ error_task_logger.error(f"执行SQL语句时发生错误: {sql}\n错误: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "分母报备调整", str(e))
+
if conn: conn.rollback()
return None
finally:
@@ -137,7 +139,7 @@ class MoleculeReportingAdjustment:
# 如果没有匹配的列,直接返回
if filtered_df.empty:
- print("DataFrame 中没有与数据库表结构匹配的列。")
+ logger.warning("DataFrame 中没有与数据库表结构匹配的列。")
return
# 筛选列之后,插入前处理 dict 类型
@@ -159,10 +161,14 @@ class MoleculeReportingAdjustment:
cursor.execute(insert_sql, tuple(row))
connection.commit()
- print(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
+
+ logger.info(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
except Exception as e:
- print("写入数据库时发生错误:", e)
+ error_task_logger.error(f"写入数据时发生错误: {e}")
+ task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ common_module.send_task_error(task_start_time, "分母报备调整", str(e))
+
connection.rollback()
finally:
cursor.close()
@@ -171,24 +177,32 @@ class MoleculeReportingAdjustment:
def clear_table(self):
"""清空表数据"""
if self.execute_sql("TRUNCATE TABLE f6_molecule_adjustment"):
- print("✅ 成功清空表数据")
+ logger.info(f"成功清空表数据")
def main(self):
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- # step1:获取宜搭数据
- self.get_yida_data()
+ try:
+ logger.info(f"开始执行任务")
+ # step1:获取宜搭数据
+ self.get_yida_data()
+ logger.info(f"获取宜搭数据成功")
- df = pd.DataFrame(self.molecule_data_list)
- df['归属月份'] = df['归属月份'].astype('Int64')
- df['归属月份'] = pd.to_datetime(df['归属月份'], unit='ms')
+ df = pd.DataFrame(self.molecule_data_list)
+ df['归属月份'] = df['归属月份'].astype('Int64')
+ df['归属月份'] = pd.to_datetime(df['归属月份'], unit='ms')
- # step2:清空BI数据表
- self.clear_table()
+ # step2:清空BI数据表
+ self.clear_table()
+ logger.info(f"清空表成功")
- # # step3:写入BI数据库
- self.write_to_bi(df)
+ # # step3:写入BI数据库
+ self.write_to_bi(df)
+ logger.info(f"写入BI数据库成功")
- common_module.send_task_status(task_start_time, "分子报备调整")
+ common_module.send_task_status(task_start_time, "分子报备调整")
+ except Exception as e:
+ error_task_logger.error(f"任务执行失败: {e}")
+ common_module.send_task_error(task_start_time, "分子报备调整", str(e))
if __name__ == '__main__':
diff --git a/back_ground_module/yida_Fpo_Jandaoyun.py b/back_ground_module/yida_Fpo_Jandaoyun.py
index 4cb63a8..947a466 100644
--- a/back_ground_module/yida_Fpo_Jandaoyun.py
+++ b/back_ground_module/yida_Fpo_Jandaoyun.py
@@ -9,23 +9,10 @@ from back_ground_module import CommonModule
import logging
from log_config import configure_task_logger, configure_error_task_logger
-# 配置日志
-# logging.basicConfig(
-# level=logging.INFO,
-# format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
-# handlers=[
-# logging.FileHandler("process.log"),
-# logging.StreamHandler()
-# ]
-# )
-# logger = logging.getLogger(__name__)
-
# 获取已经配置好的常规日志记录器
logger = configure_task_logger()
-
# 获取已经配置好的错误任务日志记录器
error_task_logger = configure_error_task_logger()
-
# 初始化 API 实例和 Token
api_instanceyd = YDAPI()
api_instance = API()
@@ -303,7 +290,7 @@ class YDFpoJiandaoyun:
except Exception as e:
error_task_logger.error(f"清除现有数据时发生错误: {e}", exc_info=True)
- def batch_create_entries(self,task_start_time):
+ def batch_create_entries(self, task_start_time):
"""批量创建条目"""
try:
if not self.all_data:
@@ -381,6 +368,7 @@ class YDFpoJiandaoyun:
except Exception as e:
error_task_logger.error(f"执行过程中发生错误: {e}", exc_info=True)
+ common_module.send_task_error(task_start_time, "宜搭FPO实例同步简道云", str(e))
if __name__ == '__main__':
diff --git a/config.py b/config.py
index f349505..1166f9b 100644
--- a/config.py
+++ b/config.py
@@ -32,7 +32,6 @@ class Config:
JCB_CONN_INFO_user = "rw_insight_gzczj"
JCB_CONN_INFO_password = "wEBT5LBHzbbhJisheCsE"
-
JIANDAOYUN_API_TOKEN = 'Bearer qygHulymo1fekJk4CIZyNKjyQAzG8CFN' # token
EFFICIENT_CAR_PICKUP_APP_ID = "6717470a0b3975ef583c6df1" # 接车宝应用id
@@ -42,6 +41,7 @@ class Config:
SCHEDULED_TASKS_ENTRY_ID = "6760e5e7672af4621ab8128a" # 定时任务表单id
JDY_TASKS_ENTRY_ID = "67ede908eb9c22261016466e" # 简道云任务派发情况表单id
+ JDY_TASKS_ERROR_ENTRY_ID = "689ae65da00c17578e27cd74" # 简道云任务派发情况表单id
EFFICIENT_CAR_PICKUP_ENTRY_ID = "67174710da507490d8ac12c1" # 接车宝表单id
EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID = "67b6f2462f9ac03b783d409a" # 接车宝客服表单id
diff --git a/doc/通用方法.md b/doc/通用方法.md
new file mode 100644
index 0000000..6d2ca4d
--- /dev/null
+++ b/doc/通用方法.md
@@ -0,0 +1,18 @@
+## 新脚本通用开头
+```python
+from datetime import datetime
+import os
+from config import Config
+import pandas as pd
+from back_ground_module import CommonModule
+from api import API
+from log_config import configure_task_logger, configure_error_task_logger
+
+
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
+output_dir = "output" # 设置输出目录
+os.makedirs(output_dir, exist_ok=True)
+common_module = CommonModule()
+api_instance = API()
+```
\ No newline at end of file
diff --git a/main.py b/main.py
index 1e4051c..eb4763f 100644
--- a/main.py
+++ b/main.py
@@ -13,27 +13,33 @@ error_task_logger = configure_error_task_logger()
def main():
- # 在程序启动时加载并执行任务
- load_tasks_on_start()
+ try:
+ # 在程序启动时加载并执行任务
+ load_tasks_on_start()
+ logger.info("程序已启动...")
- # 设置定时任务,从云端获取并保存到 csv 文件
- schedule.every().day.at("01:00").do(SampleCloudModules.fetch_and_save_tasks)
+ # 设置定时任务,从云端获取并保存到 csv 文件
+ schedule.every().day.at("01:00").do(SampleCloudModules.fetch_and_save_tasks)
- # 设置每分钟检查一次是否有新任务需要加载到队列
- schedule.every(1).minutes.do(load_tasks_and_execute)
+ # 设置每分钟检查一次是否有新任务需要加载到队列
+ schedule.every(1).minutes.do(load_tasks_and_execute)
- # 主循环,用于持续检查和执行定时任务
- while True:
- schedule.run_pending()
- time.sleep(1)
- # 每秒检查一次
- now = datetime.now()
- if now.hour == 23:
- break
+ # 主循环,用于持续检查和执行定时任务
+ while True:
+ schedule.run_pending()
+ time.sleep(1)
+ # 每秒检查一次
+ now = datetime.now()
+ if now.hour == 23:
+ logger.info("23点,程序结束。")
+ break
+ except Exception as e:
+ error_task_logger.error(f"程序异常: {e}")
if __name__ == "__main__":
# 测试时候每次从简道云获取任务列表
SampleCloudModules.fetch_and_save_tasks()
+ logger.info("任务列表已保存到 csv 文件中。")
main()
diff --git a/requirements.txt b/requirements.txt
index d8d173b..96a0670 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,11 +1,13 @@
+cpca==0.5.5
holidays==0.78
mysql_connector_repackaged==0.3.1
numpy==2.3.2
pandas==2.3.1
+playwright==1.54.0
psycopg2==2.9.10
-pymysql==1.1.1
+PyMySQL==1.1.1
python_dateutil==2.9.0.post0
Requests==2.32.4
schedule==1.2.2
tqdm==4.67.1
-mysql-connector-python==9.4.0
+pandas==2.3.1
\ No newline at end of file
diff --git a/test/logs/error_task.log b/test/logs/error_task.log
index e69de29..8fcb35e 100644
--- a/test/logs/error_task.log
+++ b/test/logs/error_task.log
@@ -0,0 +1 @@
+2025-08-12 13:50:03,815 - log测试.py - error_task_logger - ERROR - 发现了一个错误
diff --git a/test/logs/task.log b/test/logs/task.log
index e69de29..d84ab5c 100644
--- a/test/logs/task.log
+++ b/test/logs/task.log
@@ -0,0 +1 @@
+2025-08-12 13:50:03,815 - log测试.py - task_logger - INFO - 开始执行任务
diff --git a/yd_api.py b/yd_api.py
index 2f49755..229dbe5 100644
--- a/yd_api.py
+++ b/yd_api.py
@@ -3,6 +3,10 @@ import requests
import json
import numpy as np # 导入numpy库用于处理numpy数组
import time
+from log_config import configure_task_logger, configure_error_task_logger
+
+logger = configure_task_logger()
+error_task_logger = configure_error_task_logger()
# 换应用记得修改应用编码
@@ -60,6 +64,7 @@ class YDAPI:
}
res = requests.put(api, headers=headers, json=payload)
+
return res
def processes_instancesInfos(self, token, id, appType="APP_UYZ0KG6L0CCNV80GZ66O",
@@ -135,7 +140,7 @@ class YDAPI:
def read_processes_instances(self, token, formUuid, page, n, appType="APP_UYZ0KG6L0CCNV80GZ66O",
systemToken="XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2", instanceStatus="RUNNING",
- max_retries=10, delay=2, createFromTimeGMT=None, createToTimeGMT=None):
+ max_retries=10, delay=2, createFromTimeGMT=None, createToTimeGMT=None):
"""
函数功能:读取流程表单的所有数据,并加入重试机制。
@@ -176,7 +181,7 @@ class YDAPI:
while True:
if attempt >= max_retries:
- print(f"请求失败,已达最大重试次数 {max_retries},无法获取流程实例数据,跳过本次请求。")
+ error_task_logger.error(f"请求失败,已达最大重试次数 {max_retries},无法获取流程实例数据,跳过本次请求。")
break
try:
@@ -185,7 +190,7 @@ class YDAPI:
return res.json()
except requests.exceptions.RequestException as e:
- print(f"[请求失败] 错误信息: {e},正在尝试第 {attempt + 1} 次重试...")
+ logger.warning(f"请求异常: {e},正在尝试第 {attempt + 1} 次重试...")
time.sleep(delay)
attempt += 1
@@ -215,7 +220,7 @@ class YDAPI:
while True:
if attempt >= max_retries:
- print(f"请求失败,已达最大重试次数 {max_retries},跳过本次请求")
+ error_task_logger.error(f"请求失败,已达最大重试次数 {max_retries},无法获取流程实例数据,跳过本次请求。")
break
try:
@@ -223,7 +228,7 @@ class YDAPI:
res.raise_for_status() # 如果响应状态码不是2xx,则抛出HTTPError
return res.json()
except (requests.exceptions.RequestException, Exception) as e:
- print(f"请求出现异常: {e}, 正在重试({attempt + 1}/{max_retries})...")
+ logger.warning(f"请求出现异常: {e}, 正在重试({attempt + 1}/{max_retries})...")
time.sleep(delay) # 等待指定的延迟时间后再次尝试
attempt += 1
@@ -261,7 +266,7 @@ class YDAPI:
while True:
if attempt >= max_retries:
- print(f"请求失败,已达最大重试次数 {max_retries},跳过本次请求")
+ error_task_logger.error(f"请求失败,已达最大重试次数 {max_retries},无法获取流程实例数据,跳过本次请求。")
break
try:
@@ -269,7 +274,7 @@ class YDAPI:
res.raise_for_status() # 如果响应状态码不是2xx,则抛出HTTPError
return res.json()
except (requests.exceptions.RequestException, Exception) as e:
- print(f"请求出现异常: {e}, 正在重试({attempt + 1}/{max_retries})...")
+ logger.warning(f"请求出现异常: {e}, 正在重试({attempt + 1}/{max_retries})...")
time.sleep(delay) # 等待指定的延迟时间后再次尝试
attempt += 1
@@ -382,8 +387,8 @@ class YDAPI:
else:
return res.json()
- def get_form_structures(self, token, formUuid,appType = "APP_UYZ0KG6L0CCNV80GZ66O",
- systemToken = "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2",max_retries = 20):
+ def get_form_structures(self, token, formUuid, appType="APP_UYZ0KG6L0CCNV80GZ66O",
+ systemToken="XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2", max_retries=20):
"""
函数功能:获取表单结构 # 宜搭废弃
@@ -402,7 +407,7 @@ class YDAPI:
"x-acs-dingtalk-access-token": token
}
retries = 0
- data_get = {}
+ data_get = {}
payload = {
"formUuid": formUuid,
"appType": appType,