saas1.6
This commit is contained in:
@@ -0,0 +1,332 @@
|
||||
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
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
# start_time = datetime.datetime.now()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class NewExceptionTask:
|
||||
"""
|
||||
SaaS异常回访
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.get_feature_usage = None
|
||||
self.saas_create_time = None
|
||||
self.index = None
|
||||
self.date_one = None
|
||||
self.data_yichang_S = None
|
||||
self.date_list = None
|
||||
self.Smart_detection = None
|
||||
self.service_remind = None
|
||||
self.NGV_data_list = None
|
||||
self.permissions_table = None
|
||||
self.staff_id_list = None
|
||||
self.json_list = []
|
||||
self.policy_recognition = None
|
||||
self.widget_list = None
|
||||
self.private_domain = None
|
||||
self.public_domain = None
|
||||
self.public_domain_list = None
|
||||
self.different_industries = None
|
||||
self.different_industries_list = None
|
||||
self.groupnotification = None
|
||||
|
||||
def calculate_date_one(self, start_offset=0):
|
||||
"""
|
||||
计算从当前日期(或指定偏移量的日期)开始,往前遍历遇到date_list中日期的次数。
|
||||
|
||||
参数:
|
||||
- start_offset: 从当前日期起始的天数偏移量,默认为0(即今天)。负数表示过去,正数表示未来。
|
||||
|
||||
返回:
|
||||
- date_one: 遍历到date_list中日期的次数。
|
||||
"""
|
||||
jdy_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
jdy_start_time = datetime.datetime.now().strftime("%Y-%m-%d ")
|
||||
# 设置起始日期
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=start_offset)
|
||||
|
||||
# 初始化计数器
|
||||
date_one = 1
|
||||
print("当前日期:", now_time.strftime("%Y-%m-%d"))
|
||||
# 检查起始日期是否在date_list中
|
||||
if now_time.strftime("%Y-%m-%d") in self.date_list:
|
||||
date_one = 0
|
||||
print("开始次数:", date_one)
|
||||
|
||||
else:
|
||||
# 遍历日期
|
||||
for i in range(1, 10):
|
||||
new_date = now_time + datetime.timedelta(days=-i)
|
||||
new_date_str = new_date.strftime("%Y-%m-%d")
|
||||
print("遍历日期:", new_date_str)
|
||||
if new_date_str in self.date_list:
|
||||
date_one += 1
|
||||
print("节假日期:", new_date_str)
|
||||
else:
|
||||
break
|
||||
|
||||
print("遍历次数:", date_one)
|
||||
return date_one
|
||||
|
||||
@staticmethod
|
||||
def download_url_content(url, save_path):
|
||||
"""
|
||||
下载指定 URL 的内容并保存到本地文件。
|
||||
|
||||
:param url: 要下载内容的 URL
|
||||
:param save_path: 保存文件的路径
|
||||
"""
|
||||
try:
|
||||
# 发送 GET 请求以获取内容
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status() # 如果响应状态码不是 200,抛出异常
|
||||
|
||||
# 确保保存目录存在
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
|
||||
# 将内容写入文件
|
||||
with open(save_path, 'wb') as file:
|
||||
for chunk in response.iter_content(chunk_size=8192): # 分块写入,避免占用过多内存
|
||||
if chunk: # 过滤掉空块
|
||||
file.write(chunk)
|
||||
|
||||
print(f"文件已成功保存到 {save_path}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"下载失败: {e}")
|
||||
except Exception as e:
|
||||
print(f"发生错误: {e}")
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 省市区人员关系表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676512ac3e54dc3159460c0a"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.json_list = json_dict.get("data")
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取NGV数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
|
||||
self.NGV_data_list = api_instance.entry_data_list(payload).get("data", [])
|
||||
# print("NGV获取后的类型:", type(self.NGV_data_list))
|
||||
|
||||
@staticmethod
|
||||
def build_index(json_list):
|
||||
index = {}
|
||||
for json_item in json_list:
|
||||
try:
|
||||
key = (json_item['_widget_1734677164861'], json_item['_widget_1734677164862'],
|
||||
json_item['_widget_1734677164863']) # 省市区
|
||||
if '_widget_1734677164870' not in json_item: # 异常回访客服
|
||||
raise KeyError("缺少 '异常回访客服' 键")
|
||||
index[key] = json_item
|
||||
except KeyError as e:
|
||||
print(f"警告:{e},跳过该条记录: {json_item}")
|
||||
continue
|
||||
print('index', index)
|
||||
return index
|
||||
|
||||
@staticmethod
|
||||
def find_customer_service(province_name, city_name, area_name, index):
|
||||
key = (province_name, city_name, area_name)
|
||||
# print(index)
|
||||
if key not in index:
|
||||
return "数据缺失: 未找到对应的异常回访客服"
|
||||
|
||||
return index[key]
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
return None
|
||||
|
||||
def assign_customer_service(self, province_name, city_name, area_name, index):
|
||||
"""根据省市区派发给异常回访客服"""
|
||||
# try:
|
||||
customer_service_info = self.find_customer_service(province_name, city_name, area_name, index)
|
||||
customer_service = customer_service_info.get('_widget_1734677164870', {}).get('username') # 异常回访客服
|
||||
return customer_service
|
||||
# except Exception as e:
|
||||
# print(f"Error finding customer service: {e}")
|
||||
# return "分配失败,请检查", "分配失败,请检查", "分配失败,请检查"
|
||||
|
||||
def main(self):
|
||||
|
||||
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
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)
|
||||
|
||||
print("开始运行main")
|
||||
print(self.date_one)
|
||||
|
||||
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)
|
||||
|
||||
# 对整个DataFrame的所有列应用替换函数
|
||||
data_yichang = data_yichang.apply(replace_values)
|
||||
|
||||
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'
|
||||
|
||||
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'], # 运营专家
|
||||
}
|
||||
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())
|
||||
|
||||
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:
|
||||
print("未找到数据ID")
|
||||
|
||||
# 根据省市区派发给异常回访客服
|
||||
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"]}, # 活跃健康状态变化
|
||||
|
||||
"_widget_1748241895830": {"value": row["org_name"]}, # 门店名称
|
||||
|
||||
"_widget_1748241895831": {"value": row["contacts"]}, # 联系人
|
||||
|
||||
"_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_1748241895834": {"value": int(time.mktime(time.strptime(date_obj2, "%Y-%m-%d")) * 1000) if row[
|
||||
"push_day"] != '' else ''},
|
||||
# 推进日
|
||||
|
||||
"_widget_1748246808678": {"value": customer_service}, # 当前跟进人
|
||||
|
||||
"_widget_1748246808679": {"value": relationship_manager}, # 运营负责人
|
||||
|
||||
"_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_1748246808681": {"value": technician}, # 技术专家
|
||||
|
||||
"_widget_1748246808682": {"value": area_manager}, # 区域经理
|
||||
|
||||
"_widget_1748241895842": {"value": row['org_code']}, # 门店编码
|
||||
|
||||
"_widget_1748241895844": {"value": row['group_name']}, # 公司名称
|
||||
|
||||
"_widget_1748241895846": {"value": row['group_grade']}, # 公司等级
|
||||
|
||||
"_widget_1748241895847": {"value": row['region_name']}, # 大区
|
||||
|
||||
"_widget_1748241895848": {"value": row['province_name']}, # 省
|
||||
|
||||
"_widget_1748241895849": {"value": row['org_type']}, # 门店类型
|
||||
|
||||
"_widget_1748241895850": {"value": row['saas_edition_fmt']}, # 系统版本
|
||||
|
||||
"_widget_1748241895851": {"value": row['saas_customer_type']}, # saas客户类型
|
||||
|
||||
"_widget_1748241895852": {"value": row['org_stage']}, # 门店阶段
|
||||
|
||||
"_widget_1748241895853": {"value": row['contact_mobile']}, # 操作模式E.L/E.S
|
||||
|
||||
"_widget_1748241895855": {"value": row['city_name']}, # 城市
|
||||
|
||||
"_widget_1748247754304": {"value": NGV_data_id}, # 数据id
|
||||
|
||||
"_widget_1748512176655": {"value": "未处理"}, # 跟进状态
|
||||
|
||||
})
|
||||
|
||||
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, "异常服务待办派发")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = NewExceptionTask()
|
||||
start.main()
|
||||
@@ -0,0 +1,360 @@
|
||||
from datetime import date, timedelta, datetime
|
||||
import holidays
|
||||
from config import Config
|
||||
import pandas as pd
|
||||
import pymysql # 使用 pymysql 替代 mysql.connector
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
from api import API
|
||||
from back_ground_module import CommonModule
|
||||
common_module = CommonModule()
|
||||
api_instance = API()
|
||||
global last_day_end_customer_service, is_customer_service_data_id, customer_service_data_id
|
||||
|
||||
|
||||
class JCBAbnormalRevisit:
|
||||
"""接车宝异常回访"""
|
||||
def __init__(self):
|
||||
# 使用 pymysql 连接数据库
|
||||
self.daily_revisit_list = None
|
||||
self.abnormal_list = None
|
||||
self.field_mapping = {}
|
||||
self.staff_id_list = None
|
||||
self.customer_service_list = None
|
||||
|
||||
def load_all_data(self):
|
||||
# 获取接车宝异常待办
|
||||
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
||||
"entry_id": "67c156ba635191b64af8a110",
|
||||
}
|
||||
abnormal_service = api_instance.entry_data_list(payload)
|
||||
self.abnormal_list = abnormal_service.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取接车宝日常回访单
|
||||
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
||||
"entry_id": "67174710da507490d8ac12c1",
|
||||
}
|
||||
daily_revisit = api_instance.entry_data_list(payload)
|
||||
self.daily_revisit_list = daily_revisit.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
def load_cus_data(self):
|
||||
# 获取接车宝客服表单
|
||||
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
||||
"entry_id": "67b6f2462f9ac03b783d409a",
|
||||
}
|
||||
customer_service = api_instance.entry_data_list(payload)
|
||||
customer_service_list = customer_service.get("data") # api请求格式,将数据封装在data字典里
|
||||
return customer_service_list
|
||||
|
||||
def today_customer_service_list(self):
|
||||
# 获取今日接车宝派发客服顺序
|
||||
today_customer_service_list = []
|
||||
all_customer_service_list = []
|
||||
today_customer_service_start_list = []
|
||||
for row_items in self.load_cus_data():
|
||||
# print(row_items)
|
||||
customer_service_name_id = row_items.get("_widget_1740042824214", {}).get("username", {})
|
||||
customer_service_name = row_items.get("_widget_1740042824214", {}).get("name", {})
|
||||
customer_service_state = row_items.get("_widget_1740117343937", {})
|
||||
is_last_day_end = row_items.get("_widget_1740042824216", {})
|
||||
customer_service_data_id = row_items.get("_id", {})
|
||||
print(customer_service_name, customer_service_name_id, customer_service_state, is_last_day_end)
|
||||
all_customer_service_list.append(
|
||||
[customer_service_name, customer_service_name_id, customer_service_state, is_last_day_end,
|
||||
customer_service_data_id])
|
||||
if is_last_day_end == "是": # 判断是否是下次开始位置
|
||||
last_day_end_customer_service = customer_service_name_id
|
||||
is_customer_service_data_id = row_items.get("_id", {})
|
||||
|
||||
split_index = None
|
||||
for index, row in enumerate(all_customer_service_list):
|
||||
print(row[3])
|
||||
if row[3] == "是":
|
||||
split_index = index
|
||||
print(f"找到索引 {index}")
|
||||
break
|
||||
|
||||
if split_index is not None:
|
||||
# 根据索引切割列表
|
||||
first_part = all_customer_service_list[split_index:] # 索引位置及之后的行
|
||||
second_part = all_customer_service_list[:split_index] # 索引位置之前的行
|
||||
# 调换两个子列表的位置并重新组合
|
||||
today_customer_service_start_list = first_part + second_part
|
||||
else:
|
||||
# 如果没有找到“是”,保持原列表不变
|
||||
today_customer_service_start_list = all_customer_service_list
|
||||
pass
|
||||
|
||||
for index, row in enumerate(today_customer_service_start_list):
|
||||
if row[2] == "开":
|
||||
today_customer_service_list.append(row[1])
|
||||
|
||||
return today_customer_service_list, is_customer_service_data_id, all_customer_service_list
|
||||
|
||||
def send_request(self, df):
|
||||
today_customer_service_list, is_customer_service_data_id, all_customer_service_list = self.today_customer_service_list()
|
||||
# 初始化派发索引
|
||||
next_dispatcher_index = 0
|
||||
|
||||
# 显式循环分配跟进人
|
||||
follow_up_persons = []
|
||||
for _ in range(len(df)):
|
||||
follow_up_person = today_customer_service_list[next_dispatcher_index]
|
||||
follow_up_persons.append(follow_up_person)
|
||||
next_dispatcher_index = (next_dispatcher_index + 1) % len(today_customer_service_list)
|
||||
|
||||
# 添加跟进人到 DataFrame
|
||||
df["跟进人"] = follow_up_persons
|
||||
|
||||
# 获取下一个派发人
|
||||
next_dispatcher = today_customer_service_list[next_dispatcher_index]
|
||||
|
||||
new_sign_abnormal_data = [self.row_to_dict(row, self.field_mapping) for index, row in
|
||||
df.iterrows()]
|
||||
|
||||
data = {'api_key': Config.EFFICIENT_CAR_PICKUP_APP_ID, 'entry_id': "67174710da507490d8ac12c1",
|
||||
"data_list": new_sign_abnormal_data} # 派发数据
|
||||
|
||||
api_instance.entry_data_batch_create(data)
|
||||
|
||||
data1 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
||||
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
|
||||
"data_id": is_customer_service_data_id,
|
||||
"data":
|
||||
{"_widget_1740042824216": {"value": ""}, }
|
||||
} # 原来的是"_widget_1740042824216": {"value": "是"},修改昨日截至人员
|
||||
next_customer_service_data_id = None
|
||||
for index, row in enumerate(all_customer_service_list):
|
||||
print(row[3])
|
||||
if row[1] == next_dispatcher:
|
||||
next_customer_service_data_id = row[4]
|
||||
break
|
||||
|
||||
data2 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
||||
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
|
||||
"data_id": next_customer_service_data_id,
|
||||
"data":
|
||||
{"_widget_1740042824216": {"value": "是"}, }}# 明日派发起点人员
|
||||
|
||||
api_instance.entry_data_update(data1)
|
||||
api_instance.entry_data_update(data2)
|
||||
|
||||
def main(self):
|
||||
self.load_all_data()
|
||||
task_start_time =datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
data_JCB = common_module.get_jcb_details()
|
||||
|
||||
# 保存为CSV文件
|
||||
output_dir = "output" # 设置输出目录
|
||||
|
||||
# 创建输出目录(如果不存在)
|
||||
import os
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
|
||||
self.fields()
|
||||
|
||||
# 异常待办回访 近1个月开单为0客户
|
||||
# 当前日期
|
||||
current_date = datetime.now()
|
||||
current_date = current_date + timedelta(days=1)
|
||||
current_date_str = current_date.strftime("%Y-%m-%d")
|
||||
# current_date = datetime.now()
|
||||
thirty_days_ago = current_date - timedelta(days=30)
|
||||
thirty_days_ago = thirty_days_ago.date()
|
||||
abnormal_data = []
|
||||
JDY_abnormal_data = []
|
||||
JDY_revisit_data = []
|
||||
# df = pd.read_csv(os.path.join(output_dir, "JCB_异常待办.csv")) # 读取异常待办表
|
||||
# print(df)
|
||||
for index, row in data_JCB.iterrows():
|
||||
new_row = row.copy()
|
||||
new_row['开户日'] = datetime.strptime(new_row['开户日'], "%Y-%m-%d").date()
|
||||
if new_row['开户日'] < thirty_days_ago and row['近30天开单天数'] == 0 and row['客户状态'] == "留存":
|
||||
# print(row['账号'], row['开户日'], row['近30天开单天数'], row["客户状态"])
|
||||
row["日期"] = datetime.strptime(row['开户日'], "%Y-%m-%d").date()
|
||||
row['日期'] = row["日期"].strftime("%Y-%m-%d")
|
||||
abnormal_data.append(row)
|
||||
# 推送给客服
|
||||
abnormal_data = pd.DataFrame(abnormal_data)
|
||||
abnormal_data["表单类型"] = "异常待办"
|
||||
abnormal_data["派发日期"] = current_date_str
|
||||
# abnormal_data.to_excel(os.path.join(output_dir, 'JCB_异常待办.xlsx'), index=False) # 派发B(所有异常待办)
|
||||
|
||||
for abnormal_items in self.abnormal_list:
|
||||
last_send_date = abnormal_items.get("_widget_1740723898405", {}) # 派发日期
|
||||
last_30_days_orders = abnormal_items.get("_widget_1740723898401", {}) # 近30天开单数
|
||||
phone = abnormal_items.get("_widget_1740723898391", {}) # 手机号
|
||||
account = abnormal_items.get("_widget_1740723898390", {}) # 账号
|
||||
data_id = abnormal_items.get("_id", {}) # 数据id
|
||||
JDY_abnormal_data.append([data_id, account, phone, last_send_date, last_30_days_orders])
|
||||
|
||||
JDY_abnormal_data = pd.DataFrame(JDY_abnormal_data,
|
||||
columns=["数据id", "账号", "联系手机号", "派发日期",
|
||||
"近30天开单天数"]) # 派发A(简道云上异常待办)
|
||||
# JDY_abnormal_data.columns = ["数据id", "账号", "联系手机号", "派发日期", "近30天开单天数"]
|
||||
# JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_云端异常待办.xlsx'), index=False) # 派发A
|
||||
|
||||
# 将 '联系手机号' 列转换为字符串类型
|
||||
JDY_abnormal_data['联系手机号'] = JDY_abnormal_data['联系手机号'].astype(str).str.replace('.0', '')
|
||||
abnormal_data['联系手机号'] = abnormal_data['联系手机号'].astype(str)
|
||||
# JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_云端异常待办.xlsx'), index=False) # 派发A
|
||||
# abnormal_data.to_excel(os.path.join(output_dir, 'JCB_今日异常待办.xlsx'), index=False) # 派发B
|
||||
|
||||
today = datetime.now().weekday()
|
||||
|
||||
# 随机抽40条派发
|
||||
df_40 = pd.DataFrame()
|
||||
if 0 <= today <= 4:
|
||||
# if 1>2:
|
||||
# 假设 JDY_abnormal_data 和 abnormal_data 都有重复列 '重复列'
|
||||
df3 = pd.merge(JDY_abnormal_data, abnormal_data, on=["联系手机号", "账号"], how='inner',
|
||||
suffixes=('', '_y'))
|
||||
# 删除以 _y 结尾的列(即来自右侧 DataFrame 的重复列)
|
||||
df3 = df3.loc[:, ~df3.columns.str.endswith('_y')]
|
||||
df3['派发日期'] = pd.to_datetime(df3['派发日期']).dt.strftime("%Y-%m-%d")
|
||||
# df3.to_excel(os.path.join(output_dir, 'JCB_异常待办情况1.xlsx'),
|
||||
# index=False, ) # B存在,A存在 ,今日派发与历史派发都存在,派发并删历史
|
||||
|
||||
df_40 = df3[df3.index < 40]
|
||||
# df_40.to_excel(os.path.join(output_dir, 'JCB_异常待办情况2.xlsx'), index=False, )
|
||||
|
||||
for index, row in df_40.iterrows(): # 删除已推送的数据
|
||||
delete_data = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
||||
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_HISTORY_ID,
|
||||
"data_id": row["数据id"]}
|
||||
# print(delete_data)
|
||||
api_instance.entry_data_delete(delete_data)
|
||||
|
||||
# B不存在A存在 今日派发不存在,历史存在,删历史
|
||||
# 使用 outer 合并,并添加指示器列 _merge
|
||||
df_merged = pd.merge(JDY_abnormal_data, abnormal_data, on=["联系手机号", "账号"], how='outer', indicator=True,
|
||||
suffixes=('', '_y')) # outer保留所有数据,indicator标注来源
|
||||
# 筛选出只存在于 JDY_abnormal_data 中的行
|
||||
df_a_not_in_b = df_merged[df_merged['_merge'] == 'left_only']
|
||||
# 删除以 _y 结尾的列(即来自右侧 DataFrame 的重复列)
|
||||
df_a_not_in_b = df_a_not_in_b.loc[:, ~df_a_not_in_b.columns.str.endswith('_y')]
|
||||
df_a_not_in_b['派发日期'] = pd.to_datetime(df_a_not_in_b['派发日期']).dt.strftime("%Y-%m-%d")
|
||||
# 保存到 Excel 文件
|
||||
# df_a_not_in_b.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_A存在B不存在.xlsx'), index=False)
|
||||
for index, row in df_a_not_in_b.iterrows(): # 删除已推送的数据
|
||||
delete_data = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
||||
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_HISTORY_ID,
|
||||
"data_id": row["数据id"]}
|
||||
# print(delete_data)
|
||||
api_instance.entry_data_delete(delete_data)
|
||||
|
||||
# B存在A不存在 今日派发存在,历史不存在,为新增异常,直接派发
|
||||
df_merged = pd.merge(JDY_abnormal_data, abnormal_data, on=["联系手机号", "账号"], how='outer', indicator=True,
|
||||
suffixes=('_x', '')) # outer保留所有数据,indicator标注来源
|
||||
# df_merged.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在_134434.xlsx'), index=False)
|
||||
# 筛选出只存在于 JDY_abnormal_data 中的行
|
||||
df_b_not_in_a = df_merged[df_merged['_merge'] == 'right_only']
|
||||
# df_b_not_in_a.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在_111.xlsx'), index=False)
|
||||
# 删除以 _y 结尾的列(即来自右侧 DataFrame 的重复列)
|
||||
df_b_not_in_a = df_b_not_in_a.loc[:, ~df_b_not_in_a.columns.str.endswith('_x')]
|
||||
# df_b_not_in_a.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在_122.xlsx'), index=False)
|
||||
df_b_not_in_a['派发日期'] = pd.to_datetime(df_b_not_in_a['派发日期']).dt.strftime("%Y-%m-%d")
|
||||
# 保存到 Excel 文件
|
||||
# df_b_not_in_a.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_B存在A不存在.xlsx'), index=False)
|
||||
|
||||
# 合并两个当日派发的df
|
||||
df_abnormal_data = pd.concat([df_40, df_b_not_in_a], ignore_index=True)
|
||||
# df_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_合并当日派发.xlsx'), index=False)
|
||||
|
||||
for abnormal_items in self.daily_revisit_list: # 遍历云端已经派发的数据
|
||||
account = abnormal_items.get("_widget_1739258942667", {}) # 账号
|
||||
sub_date = abnormal_items.get("createTime", {}) # 提交时间
|
||||
update_date = abnormal_items.get("updateTime", {}) # 更新时间
|
||||
entry_style = abnormal_items.get("_widget_1739951204545", {}) # 表单类型
|
||||
entry_type = abnormal_items.get("flowState", {}) # 表单状态 0流转中 1流转完成 2 手动结束
|
||||
|
||||
data_id = abnormal_items.get("_id", {}) # 数据id
|
||||
JDY_revisit_data.append([data_id, account, sub_date, update_date, entry_style, entry_type])
|
||||
|
||||
JDY_revisit_data = pd.DataFrame(JDY_revisit_data)
|
||||
JDY_revisit_data.columns = ["数据id", "账号", "提交时间", "更新时间", "表单类型", "表单状态"]
|
||||
# JDY_revisit_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_原始数据.xlsx'), index=False)
|
||||
|
||||
filtered_data = JDY_revisit_data[JDY_revisit_data['表单类型'] == '异常待办'] # 过滤表单类型
|
||||
# filtered_data = filtered_data[filtered_data['表单状态'] == 1] # 过滤表单状态
|
||||
# filtered_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_过滤数据.xlsx'), index=False)
|
||||
|
||||
filtered_data['提交时间'] = pd.to_datetime(filtered_data['提交时间']).dt.strftime("%Y-%m-%d")
|
||||
latest_update_time = filtered_data.groupby('账号')['提交时间'].max().reset_index()
|
||||
latest_update_time.rename(columns={'提交时间': '最新提交时间'}, inplace=True)
|
||||
|
||||
|
||||
filtered_data_with_latest = pd.merge(
|
||||
filtered_data,
|
||||
latest_update_time,
|
||||
left_on=['账号', '提交时间'],
|
||||
right_on=['账号', '最新提交时间']
|
||||
)
|
||||
|
||||
# 过滤出每个账号中提交时间为最新的记录
|
||||
latest_JDY_abnormal_data = filtered_data_with_latest[
|
||||
filtered_data_with_latest['提交时间'] == filtered_data_with_latest['最新提交时间']
|
||||
]
|
||||
# latest_JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_最新数据_1.xlsx'), index=False)
|
||||
|
||||
|
||||
latest_JDY_abnormal_data['提交时间'] = pd.to_datetime(latest_JDY_abnormal_data['提交时间']).dt.strftime("%Y-%m-%d")
|
||||
|
||||
thirty_days_ago = (current_date - timedelta(days=30)).strftime("%Y-%m-%d")
|
||||
|
||||
final_JDY_abnormal_data = latest_JDY_abnormal_data[latest_JDY_abnormal_data['提交时间'] > thirty_days_ago] # 筛选出提交时间为近30天的数据
|
||||
|
||||
# final_JDY_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_日常回访_最新数据.xlsx'), index=False)
|
||||
|
||||
df_abnormal_data = df_abnormal_data[~df_abnormal_data['账号'].isin(final_JDY_abnormal_data['账号'])]
|
||||
# empty_num = df_abnormal_data['手机号'].isnull().sum()
|
||||
df_abnormal_data = df_abnormal_data[df_abnormal_data["联系手机号"] != "None"]
|
||||
# df_abnormal_data.to_excel(os.path.join(output_dir, 'JCB_异常待办情况_派发数据.xlsx'), index=False)
|
||||
|
||||
self.send_request(df_abnormal_data)
|
||||
common_module.send_task_status(task_start_time, "接车宝异常派发")
|
||||
|
||||
|
||||
# df_abnormal_data = [self.row_to_dict(row, self.field_mapping) for index, row in
|
||||
# df_abnormal_data.iterrows()]
|
||||
#
|
||||
# data = {'api_key': Config.EFFICIENT_CAR_PICKUP_APP_ID, 'entry_id':"67174710da507490d8ac12c1",
|
||||
# "data_list": df_abnormal_data}
|
||||
#
|
||||
#
|
||||
# result = api_instance.entry_data_batch_create(data)
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
# print(field_mapping)
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
# print(col_name, widget_id)
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {"日期": "_widget_1739252804406", "产品名称": "_widget_1739252804397",
|
||||
"账号": "_widget_1739258942667", "联系手机号": "_widget_1739252804407",
|
||||
"使用时长": "_widget_1739252804409", "开户日": "_widget_1739252804396",
|
||||
"到期日": "_widget_1739252804408", "续约日": "_widget_1739252804410",
|
||||
"客户状态": "_widget_1739252804400", "近一周开单量": "_widget_1739252804413",
|
||||
"近一周是否活跃": "_widget_1739252804414",
|
||||
"G状态:近30天开单大于等于10天": "_widget_1739252804415",
|
||||
"当月开单天数": "_widget_1739252804416", "近30天开单天数": "_widget_1739252804417",
|
||||
"当月G天数": "_widget_1739252804418", "日分区": "_widget_1739252804419",
|
||||
"表单类型": "_widget_1739951204545", "派发日期": "_widget_1740036367181",
|
||||
"跟进人": "_widget_1740043340255",
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start = JCBAbnormalRevisit()
|
||||
start.main()
|
||||
# if result is not None:
|
||||
# print(result.head()) # 打印前几行数据
|
||||
@@ -0,0 +1,255 @@
|
||||
from datetime import date, timedelta, datetime
|
||||
import holidays
|
||||
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
|
||||
|
||||
common_module = CommonModule()
|
||||
api_instance = API()
|
||||
|
||||
|
||||
class JCBEfficientCarPickup:
|
||||
"""接车宝日常回访"""
|
||||
def __init__(self):
|
||||
# 使用 pymysql 连接数据库
|
||||
self.field_mapping = {}
|
||||
self.staff_id_list = None
|
||||
self.customer_service_list = None
|
||||
|
||||
def load_cus_data(self):
|
||||
# 获取接车宝客服表单
|
||||
payload = {"api_key": "6717470a0b3975ef583c6df1",
|
||||
"entry_id": "67b6f2462f9ac03b783d409a",
|
||||
}
|
||||
customer_service = api_instance.entry_data_list(payload)
|
||||
customer_service_list = customer_service.get("data") # api请求格式,将数据封装在data字典里
|
||||
return customer_service_list
|
||||
|
||||
def today_customer_service_list(self):
|
||||
# 获取今日接车宝派发客服顺序
|
||||
today_customer_service_list = []
|
||||
all_customer_service_list = []
|
||||
today_customer_service_start_list = []
|
||||
for row_items in self.load_cus_data():
|
||||
# print(row_items)
|
||||
customer_service_name_id = row_items.get("_widget_1740042824214", {}).get("username", {})
|
||||
customer_service_name = row_items.get("_widget_1740042824214", {}).get("name", {})
|
||||
customer_service_state = row_items.get("_widget_1740117343937", {})
|
||||
is_last_day_end = row_items.get("_widget_1740042824216", {})
|
||||
customer_service_data_id = row_items.get("_id", {})
|
||||
print(customer_service_name, customer_service_name_id, customer_service_state, is_last_day_end)
|
||||
all_customer_service_list.append(
|
||||
[customer_service_name, customer_service_name_id, customer_service_state, is_last_day_end,
|
||||
customer_service_data_id])
|
||||
if is_last_day_end == "是": # 判断是否是下次开始位置
|
||||
last_day_end_customer_service = customer_service_name_id
|
||||
is_customer_service_data_id = row_items.get("_id", {})
|
||||
|
||||
split_index = None
|
||||
for index, row in enumerate(all_customer_service_list):
|
||||
print(row[3])
|
||||
if row[3] == "是":
|
||||
split_index = index
|
||||
print(f"找到索引 {index}")
|
||||
break
|
||||
|
||||
if split_index is not None:
|
||||
# 根据索引切割列表
|
||||
first_part = all_customer_service_list[split_index:] # 索引位置及之后的行
|
||||
second_part = all_customer_service_list[:split_index] # 索引位置之前的行
|
||||
# 调换两个子列表的位置并重新组合
|
||||
today_customer_service_start_list = first_part + second_part
|
||||
else:
|
||||
# 如果没有找到“是”,保持原列表不变
|
||||
today_customer_service_start_list = all_customer_service_list
|
||||
pass
|
||||
|
||||
for index, row in enumerate(today_customer_service_start_list):
|
||||
if row[2] == "开":
|
||||
today_customer_service_list.append(row[1])
|
||||
|
||||
return today_customer_service_list, is_customer_service_data_id, all_customer_service_list
|
||||
|
||||
def send_request(self, df):
|
||||
today_customer_service_list, is_customer_service_data_id, all_customer_service_list = self.today_customer_service_list()
|
||||
# 初始化派发索引
|
||||
next_dispatcher_index = 0
|
||||
|
||||
# 显式循环分配跟进人
|
||||
follow_up_persons = []
|
||||
for _ in range(len(df)):
|
||||
follow_up_person = today_customer_service_list[next_dispatcher_index]
|
||||
follow_up_persons.append(follow_up_person)
|
||||
next_dispatcher_index = (next_dispatcher_index + 1) % len(today_customer_service_list)
|
||||
|
||||
# 添加跟进人到 DataFrame
|
||||
df["跟进人"] = follow_up_persons
|
||||
|
||||
# 获取下一个派发人
|
||||
next_dispatcher = today_customer_service_list[next_dispatcher_index]
|
||||
|
||||
new_sign_abnormal_data = [self.row_to_dict(row, self.field_mapping) for index, row in
|
||||
df.iterrows()]
|
||||
|
||||
data = {'api_key': Config.EFFICIENT_CAR_PICKUP_APP_ID, 'entry_id': Config.EFFICIENT_CAR_PICKUP_ENTRY_ID,
|
||||
"data_list": new_sign_abnormal_data}
|
||||
|
||||
result = api_instance.entry_data_batch_create(data)
|
||||
|
||||
data1 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
||||
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
|
||||
"data_id": is_customer_service_data_id,
|
||||
"data":
|
||||
{"_widget_1740042824216": {"value": ""}, }
|
||||
} # 原来的是"_widget_1740042824216": {"value": "是"},修改昨日截至人员
|
||||
next_customer_service_data_id = None
|
||||
for index, row in enumerate(all_customer_service_list):
|
||||
print(row[3])
|
||||
if row[1] == next_dispatcher:
|
||||
next_customer_service_data_id = row[4]
|
||||
break
|
||||
|
||||
data2 = {"api_key": Config.EFFICIENT_CAR_PICKUP_APP_ID,
|
||||
"entry_id": Config.EFFICIENT_CAR_PICKUP_CUSTOMER_SERVICE_ID,
|
||||
"data_id": next_customer_service_data_id,
|
||||
"data":
|
||||
{"_widget_1740042824216": {"value": "是"}, }}
|
||||
|
||||
api_instance.entry_data_update(data1)
|
||||
api_instance.entry_data_update(data2)
|
||||
|
||||
def main(self):
|
||||
task_start_time =datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
data_JCB = common_module.get_jcb_details()
|
||||
print(data_JCB)
|
||||
|
||||
# 保存为CSV文件
|
||||
output_dir = "output" # 设置输出目录
|
||||
|
||||
# 创建输出目录(如果不存在)
|
||||
import os
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# data_JCB.to_csv(os.path.join(output_dir, 'JCB_all_data.csv'), index=False)
|
||||
self.fields()
|
||||
|
||||
# 新签异常待办回访。
|
||||
# 当前日期
|
||||
current_date = datetime.now()
|
||||
current_date = current_date + timedelta(days=0)
|
||||
current_date_str = current_date.strftime("%Y-%m-%d")
|
||||
|
||||
seven_days_ago = current_date - timedelta(days=7)
|
||||
seven_days_ago = seven_days_ago.date()
|
||||
# print(three_days_ago)
|
||||
new_sign_abnormal = []
|
||||
|
||||
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)
|
||||
|
||||
new_sign_abnormal = pd.DataFrame(new_sign_abnormal)
|
||||
new_sign_abnormal["表单类型"] = "新签异常待办"
|
||||
new_sign_abnormal["派发日期"] = current_date_str
|
||||
|
||||
self.send_request(new_sign_abnormal) # 发送请求
|
||||
|
||||
# 优质客户转商机
|
||||
# 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
|
||||
|
||||
customer_to_opportunity = pd.DataFrame(customer_to_opportunity)
|
||||
customer_to_opportunity["表单类型"] = "续约优质客户转商机"
|
||||
customer_to_opportunity["派发日期"] = current_date_str
|
||||
|
||||
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, "接车宝日常派发")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
# print(field_mapping)
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
# print(col_name, widget_id)
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {"日期": "_widget_1739252804406", "产品名称": "_widget_1739252804397",
|
||||
"账号": "_widget_1739258942667", "联系手机号": "_widget_1739252804407",
|
||||
"使用时长": "_widget_1739252804409", "开户日": "_widget_1739252804396",
|
||||
"到期日": "_widget_1739252804408", "续约日": "_widget_1739252804410",
|
||||
"客户状态": "_widget_1739252804400", "近一周开单量": "_widget_1739252804413",
|
||||
"近一周是否活跃": "_widget_1739252804414",
|
||||
"G状态:近30天开单大于等于10天": "_widget_1739252804415",
|
||||
"当月开单天数": "_widget_1739252804416", "近30天开单天数": "_widget_1739252804417",
|
||||
"当月G天数": "_widget_1739252804418", "日分区": "_widget_1739252804419",
|
||||
"表单类型": "_widget_1739951204545", "派发日期": "_widget_1740036367181",
|
||||
"跟进人": "_widget_1740043340255",
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start = JCBEfficientCarPickup()
|
||||
start.main()
|
||||
@@ -0,0 +1,26 @@
|
||||
from back_ground_module.common_module import CommonModule
|
||||
from back_ground_module.revisit_new_services_180 import NewServicesRevisit
|
||||
from back_ground_module.update_NGV_data import UpdateNGVData
|
||||
from back_ground_module.revisit_key_customer import KeyCustomerRevisit
|
||||
from back_ground_module.revisit_renew_services_90_120_180 import RenewServicesRevisit
|
||||
from back_ground_module.update_all_NGV_data_daily import UpdateAllNGVDataDaily
|
||||
from back_ground_module.JCB_efficient_car_pickup import JCBEfficientCarPickup
|
||||
from back_ground_module.JCB_abnormal_revisit import JCBAbnormalRevisit
|
||||
from back_ground_module.data_Support_Private_Mini_Program import importSYXCXData
|
||||
from back_ground_module.data_Support_Commission import importCommissionData
|
||||
from back_ground_module.data_Support_DifferentIndustries import importDifferentIndustriesData
|
||||
from back_ground_module.data_Support_GroupNotification import importGroupNotificationData
|
||||
from back_ground_module.update_email_to_store_daily_use import EmailProcessor
|
||||
from back_ground_module.Exception_Task import NewExceptionTask
|
||||
from back_ground_module.revisit_all_information import RevisitAllInformation
|
||||
from back_ground_module.yida_Fpo_Jandaoyun import YDFpoJiandaoyun
|
||||
from back_ground_module.get_process_time import TimeConsumingProcess
|
||||
from back_ground_module.update_BI_CRM_info import CRMDataProcessor
|
||||
from back_ground_module.update_ID_form import update_ID_form
|
||||
from back_ground_module.indtall_event_dispatcher import InstallEventDispatcher
|
||||
from back_ground_module.新签180天重构 import NewServicesRevisitTest
|
||||
from back_ground_module.update_denominator_reporting_adjustment_to_bi import DenominatorReportingAdjustment
|
||||
from back_ground_module.update_molecule_reporting_adjustment_to_bi import MoleculeReportingAdjustment
|
||||
from back_ground_module.import_performance_data import ImportPerformanceData
|
||||
from back_ground_module.data_monitor import DataMonitor
|
||||
from back_ground_module.new_dealer_service_order_to_bi import NewDealerServiceOrderToBI
|
||||
@@ -0,0 +1,620 @@
|
||||
from datetime import datetime, timezone, timedelta, date, UTC
|
||||
import holidays
|
||||
from config import Config
|
||||
import psycopg2
|
||||
import pandas as pd
|
||||
import pymysql
|
||||
from api import API
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
|
||||
api_instance = API()
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class CommonModule:
|
||||
"""工具类"""
|
||||
|
||||
def __init__(self):
|
||||
# 初始化中国节假日对象
|
||||
self.cn_holidays = holidays.country_holidays('CN', years=2025)
|
||||
# 创建一个存储日期的集合,用于去重
|
||||
self.date_set = set()
|
||||
self.conn = Config.CONN_INFO
|
||||
|
||||
def time_to_UTC(self, time_input):
|
||||
"""
|
||||
时间转为UTC格式(兼容字符串和Timestamp输入)
|
||||
:param time_input: 支持以下格式:
|
||||
- 字符串格式:"2025-06-05 14:30:00" 或 "2025-06-05"
|
||||
- Pandas Timestamp对象
|
||||
:return: ISO8601格式的UTC时间字符串(如"2025-06-05T06:30:00Z")
|
||||
"""
|
||||
# 处理Timestamp输入
|
||||
if isinstance(time_input, pd.Timestamp):
|
||||
dt = time_input.to_pydatetime()
|
||||
# 处理字符串输入
|
||||
else:
|
||||
try:
|
||||
dt = datetime.strptime(time_input, "%Y-%m-%d %H:%M:%S")
|
||||
except ValueError:
|
||||
try:
|
||||
dt = datetime.strptime(time_input, "%Y-%m-%d")
|
||||
except ValueError as e:
|
||||
raise ValueError(f"不支持的日期格式: {time_input}") from e
|
||||
|
||||
# 转换为UTC时间(假设原始时间为东八区)
|
||||
dt_utc = dt - timedelta(hours=8)
|
||||
return dt_utc.replace(tzinfo=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
def get_holiday_list(self, year=None):
|
||||
"""
|
||||
获取指定年份的节假日和周日列表。
|
||||
如果没有提供年份,则使用当前年份。
|
||||
"""
|
||||
if year is None:
|
||||
year = date.today().year
|
||||
|
||||
# 清空集合,防止重复添加数据
|
||||
self.date_set.clear()
|
||||
|
||||
# 添加节假日到集合
|
||||
for holiday in self.cn_holidays:
|
||||
if holiday.year == year:
|
||||
self.date_set.add(str(holiday))
|
||||
|
||||
# 添加该年的所有周日到集合
|
||||
start_date = date(year, 1, 1)
|
||||
end_date = date(year, 12, 31)
|
||||
current_date = start_date
|
||||
while current_date <= end_date:
|
||||
if current_date.weekday() == 6: # 周日的weekday值为6
|
||||
self.date_set.add(str(current_date))
|
||||
current_date += timedelta(days=1)
|
||||
|
||||
# 将集合转换为排序后的列表
|
||||
return sorted(list(self.date_set), reverse=False)
|
||||
|
||||
def get_ngv_details(self, days_back=1):
|
||||
"""
|
||||
从固定的数据库中获取前几天的NGV明细。
|
||||
参数 `days_back` 表示相对于今天的天数偏移量,默认为1(即前一天)。
|
||||
返回包含NGV明细的pandas DataFrame。
|
||||
"""
|
||||
try:
|
||||
# 获得连接
|
||||
conn = psycopg2.connect(**self.conn)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
now_time = datetime.now()
|
||||
target_time = now_time + timedelta(days=-days_back)
|
||||
target_date_id = int(target_time.strftime('%Y%m%d')) # 获取目标日期
|
||||
|
||||
# sql语句查询
|
||||
sql = f"""
|
||||
SELECT * FROM "public"."holo_ads_report_saas_profile_ngv_detail_d" WHERE "date_id" = '{target_date_id}' ;
|
||||
"""
|
||||
|
||||
# 执行语句并获取结果集
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall()
|
||||
all_fields = cursor.description
|
||||
|
||||
# 执行结果转化为dataframe
|
||||
col = [i[0] for i in all_fields]
|
||||
data_NGV = pd.DataFrame(rows, columns=col)
|
||||
|
||||
# 尝试自动解析日期时间字符串
|
||||
time_format = "%Y-%m-%d %H:%M:%S"
|
||||
if 'saas_create_time' in data_NGV.columns:
|
||||
data_NGV['saas_create_time'] = pd.to_datetime(data_NGV['saas_create_time'], format=time_format,
|
||||
errors='coerce')
|
||||
data_NGV['saas_create_time'] = data_NGV['saas_create_time'].dt.strftime('%Y-%m-%d')
|
||||
|
||||
# 关闭游标和连接
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
return data_NGV
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_yichang_details(self, days_back=1):
|
||||
"""
|
||||
从固定的数据库中获取前几天的异常明细。
|
||||
参数 `days_back` 表示相对于今天的天数偏移量,默认为1(即前一天)。
|
||||
返回包含异常明细的pandas DataFrame。
|
||||
"""
|
||||
try:
|
||||
# 获得连接
|
||||
conn = psycopg2.connect(**self.conn)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
now_time = datetime.now()
|
||||
target_time = now_time + timedelta(days=-days_back)
|
||||
target_date_id = int(target_time.strftime('%Y%m%d')) # 获取目标日期
|
||||
|
||||
# sql语句查询
|
||||
sql = f"""SELECT * FROM "public"."holo_ads_dataservice_saas_org_health_warning" WHERE "pt" = '{target_date_id}' and "org_type" = '一般';"""
|
||||
|
||||
# 执行语句并获取结果集
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall()
|
||||
all_fields = cursor.description
|
||||
|
||||
# 执行结果转化为dataframe
|
||||
col = [i[0] for i in all_fields]
|
||||
data_yichang = pd.DataFrame(rows, columns=col)
|
||||
|
||||
# 尝试自动解析日期时间字符串
|
||||
time_format = "%Y-%m-%d %H:%M:%S"
|
||||
if 'saas_create_time' in data_yichang.columns:
|
||||
data_yichang['saas_create_time'] = pd.to_datetime(data_yichang['saas_create_time'], format=time_format,
|
||||
errors='coerce')
|
||||
data_yichang['saas_create_time'] = data_yichang['saas_create_time'].dt.strftime('%Y-%m-%d')
|
||||
|
||||
# 关闭游标和连接
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
return data_yichang
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_saas_data(self):
|
||||
pass
|
||||
|
||||
def get_jcb_details(self, ):
|
||||
"""
|
||||
从固定的数据库中获取前几天的NGV明细。
|
||||
参数 `days_back` 表示相对于今天的天数偏移量,默认为1(即前一天)。
|
||||
返回包含NGV明细的pandas DataFrame。
|
||||
"""
|
||||
# 保存为CSV文件
|
||||
output_dir = "output" # 设置输出目录
|
||||
|
||||
# 创建输出目录(如果不存在)
|
||||
import os
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
target_date_id = "接车宝" # 获取目标日期
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM jdy_hs_holo_dws_sales_magic_box_ngv_d WHERE 产品名称 = '{target_date_id}';
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_NGV = pd.DataFrame(rows)
|
||||
if data_NGV.shape[1] > 16:
|
||||
data_NGV = data_NGV.iloc[:, :16]
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_NGV = pd.DataFrame()
|
||||
|
||||
# 尝试自动解析日期时间字符串
|
||||
time_format = "%Y-%m-%d %H:%M:%S"
|
||||
if 'saas_create_time' in data_NGV.columns:
|
||||
data_NGV['saas_create_time'] = pd.to_datetime(data_NGV['saas_create_time'], format=time_format,
|
||||
errors='coerce')
|
||||
data_NGV['saas_create_time'] = data_NGV['saas_create_time'].dt.strftime('%Y-%m-%d')
|
||||
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = [
|
||||
"日期",
|
||||
"产品名称",
|
||||
"账号", # 唯一值
|
||||
"联系手机号",
|
||||
"开户日",
|
||||
"使用时长",
|
||||
"续约日",
|
||||
"到期日",
|
||||
"客户状态",
|
||||
"近一周开单量",
|
||||
"近一周是否活跃",
|
||||
"G状态:近30天开单大于等于10天",
|
||||
"当月开单天数",
|
||||
"近30天开单天数",
|
||||
"当月G天数",
|
||||
"日分区",
|
||||
]
|
||||
data_NGV.columns = headers
|
||||
|
||||
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)
|
||||
|
||||
return data_NGV
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_syxcx_details(self, ):
|
||||
"""
|
||||
从f6operation_data_relay数据库中获取私域小程序数据。
|
||||
返回pandas DataFrame。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM jiandaoyun_dailyvisit_privateminiprogram;
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_SY = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_SY = pd.DataFrame()
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = [
|
||||
"公司ID", "公众号名称", "小程序模板类型", "是否开通微信商城", "上架商品数",
|
||||
"上架套餐卡数", "上架实体商品数", "上架项目数", "上架套餐数", "微信公众号粉丝数",
|
||||
"微信公众号绑定手机粉丝数", "是否开通微信小程序", "微信小程序绑定用户数", "微信小程序绑定手机用户量",
|
||||
"微信订单数", "微信支付订单量", "线下订单数"
|
||||
]
|
||||
|
||||
data_SY.columns = headers
|
||||
|
||||
return data_SY
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_commission_details(self, ):
|
||||
"""
|
||||
从f6operation_data_relay数据库中获取小六提成数据。
|
||||
返回pandas DataFrame。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM JianDaoYun_DailyVisit_Commission;
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_commission = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_commission = pd.DataFrame()
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = [
|
||||
"门店id", "提成类型_二级分类", "提成基数(本月)", "提成基数(上月)", "公司id", "门店编码", "门店名称"
|
||||
]
|
||||
|
||||
data_commission.columns = headers
|
||||
|
||||
return data_commission
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_differentindustries_details(self, ):
|
||||
"""
|
||||
从f6operation_data_relay数据库中获取小六提成数据。
|
||||
返回pandas DataFrame。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM JianDaoYun_DailyVisit_DifferentIndustries;
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_commission = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_commission = pd.DataFrame()
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = [
|
||||
"门店id", "商品名称", "服务期结束时间", "门店名称", "公司id", "门店编码"
|
||||
]
|
||||
|
||||
data_commission.columns = headers
|
||||
|
||||
return data_commission
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_perforamnce_details(self, ):
|
||||
"""
|
||||
从f6operation_data_relay数据库中获取履约表数据
|
||||
返回pandas DataFrame。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM SAAS_Fulfillment_Details;
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_commission = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_commission = pd.DataFrame()
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = ["订单id", "f6订单编号", "宜搭的实例id", "商品id", "商品名称", "发布商品类型", "发布商品类型描述",
|
||||
"门店id", "门店名称", "门店编码", "运营负责人", "区域经理", "商户中心id", "saas开户时间",
|
||||
"公司id", "公司名称", "产生来源", "产生来源描述", "类型", "类型描述", "服务年份",
|
||||
"订单服务期第几年", "服务期起始时间", "服务期结束时间", "提成业务类型", "提成类别",
|
||||
"下单支付成功时间", "实付金额", "系统成本价", "版本费", "服务费", "介绍人员工ID",
|
||||
"介绍业绩归属人员工ID", "处理人ID employee_id", "业绩归属人员工ID", "操作时间",
|
||||
"处理人是否跟进,0: 未跟进,1: 已跟进", "满意度评分", "评价完成时间", "介绍人用户类型",
|
||||
"下单支付成功日期", "培训完成时间", "订单所处阶段", "日分区"]
|
||||
data_commission.columns = headers
|
||||
|
||||
float_columns = ["实付金额", "系统成本价", "版本费", "服务费"]
|
||||
for col in float_columns:
|
||||
data_commission[col] = data_commission[col].astype(float)
|
||||
|
||||
return data_commission
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_commission_details(self, ):
|
||||
"""
|
||||
从f6operation_data_relay数据库中获取小六提成数据。
|
||||
返回pandas DataFrame。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM JianDaoYun_DailyVisit_Commission;
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_commission = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_commission = pd.DataFrame()
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = [
|
||||
"门店id", "提成类型_二级分类", "提成基数(本月)", "提成基数(上月)", "公司id", "门店编码", "门店名称"
|
||||
]
|
||||
|
||||
data_commission.columns = headers
|
||||
|
||||
return data_commission
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
def get_GroupNotification_details(self, ):
|
||||
"""
|
||||
从f6operation_data_relay数据库中获取小六提成数据。
|
||||
返回pandas DataFrame。
|
||||
"""
|
||||
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
conn = pymysql.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
database=Config.BI_CONN_INFO_database,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM jiandaoyun_dailyvisit_groupnotification;
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_commission = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_commission = pd.DataFrame()
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
headers = [
|
||||
"公司id", "是否启动短信功能", "是否购买短信包", "累计购买总数", "累计发送成功总人数", "剩余短信条数",
|
||||
"实付总金额", "短信剩余量是否小于20%", "第一次短信购买时间", "最近一次短信购买时间"
|
||||
]
|
||||
|
||||
data_commission.columns = headers
|
||||
|
||||
return data_commission
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
from datetime import datetime, timedelta, UTC, timezone
|
||||
|
||||
def send_task_status(self, task_start_time: str, task_name: str) -> None:
|
||||
"""
|
||||
将任务状态发送到简道云(开始时间为北京时间,需转换到 UTC)
|
||||
: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()
|
||||
|
||||
# 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")
|
||||
print(task_end_iso)
|
||||
print(task_start_iso)
|
||||
|
||||
# 6. 构造请求数据(所有时间以 UTC 格式发送)
|
||||
payload = {
|
||||
"api_key": Config.SCHEDULED_TASKS_APP_ID,
|
||||
"entry_id": Config.JDY_TASKS_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},
|
||||
}
|
||||
}
|
||||
|
||||
# 7. 发送请求
|
||||
response = api_instance.data_batch_create(payload)
|
||||
logger.info(f"任务状态发送成功: {response}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"任务状态发送失败: {e}")
|
||||
@@ -0,0 +1,83 @@
|
||||
# -*- 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
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
|
||||
|
||||
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)): # 删除历史数据
|
||||
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
|
||||
|
||||
data_commission = common_module.get_commission_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.Commission_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, "小六提成数据支撑")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {
|
||||
"门店id": "_widget_1742884710674",
|
||||
"提成类型_二级分类": "_widget_1742884710675",
|
||||
"提成基数(本月)": "_widget_1742884710676",
|
||||
"提成基数(上月)": "_widget_1742884710677",
|
||||
"公司id": "_widget_1748930441629",
|
||||
"门店编码": "_widget_1748931089356",
|
||||
"门店名称": "_widget_1748931089357"
|
||||
}
|
||||
if __name__ == '__main__':
|
||||
start = importCommissionData()
|
||||
start.main()
|
||||
@@ -0,0 +1,81 @@
|
||||
# -*- 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
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
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)): # 删除历史数据
|
||||
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
|
||||
|
||||
|
||||
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}
|
||||
|
||||
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, "异业合作数据支撑")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {
|
||||
"门店id": "_widget_1742884829007",
|
||||
"商品名称": "_widget_1742884829008",
|
||||
"服务期结束时间": "_widget_1742884829009",
|
||||
"门店名称": "_widget_1748931208851",
|
||||
"公司id": "_widget_1748930826642",
|
||||
"门店编码": "_widget_1748931208852"
|
||||
}
|
||||
if __name__ == '__main__':
|
||||
start = importDifferentIndustriesData()
|
||||
start.main()
|
||||
@@ -0,0 +1,97 @@
|
||||
# -*- 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
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
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)): # 删除历史数据
|
||||
|
||||
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'])
|
||||
except Exception as e:
|
||||
print(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}
|
||||
|
||||
api_instance.entry_data_batch_delete(delete_payload)
|
||||
|
||||
|
||||
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, "短信数据支撑")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {
|
||||
"公司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()
|
||||
start.main()
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- 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
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
|
||||
|
||||
class importSYXCXData:
|
||||
"""私域小程序数据支撑"""
|
||||
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.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:
|
||||
delete_data = {"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_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])
|
||||
|
||||
# 保存到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, "私域小程序数据支撑")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {
|
||||
"公司ID": "_widget_1742795002375",
|
||||
"公众号名称": "_widget_1742795002376",
|
||||
"小程序模板类型": "_widget_1742795002377",
|
||||
"是否开通微信商城": "_widget_1742795002378",
|
||||
"上架商品数": "_widget_1742795002379",
|
||||
"上架套餐卡数": "_widget_1742795002380",
|
||||
"上架实体商品数": "_widget_1742795002381",
|
||||
"上架项目数": "_widget_1742795002382",
|
||||
"上架套餐数": "_widget_1742795002383",
|
||||
"微信公众号粉丝数": "_widget_1742795002384",
|
||||
"微信公众号绑定手机粉丝数": "_widget_1742795002385",
|
||||
"是否开通微信小程序": "_widget_1742795002386",
|
||||
"微信小程序绑定用户数": "_widget_1742795002387",
|
||||
"微信小程序绑定手机用户量": "_widget_1742795002388",
|
||||
"微信订单数": "_widget_1742795002389",
|
||||
"微信支付订单量": "_widget_1742795002390",
|
||||
"线下订单数": "_widget_1742795002391"
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = importSYXCXData()
|
||||
start.main()
|
||||
@@ -0,0 +1,400 @@
|
||||
"""字段监控"""
|
||||
import sys
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import pandas as pd
|
||||
import zipfile
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import json
|
||||
import requests
|
||||
from api import API
|
||||
import time
|
||||
import os
|
||||
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()
|
||||
common_tools = CommonModule()
|
||||
|
||||
# ---------------------------- 配置项 ----------------------------
|
||||
class Config:
|
||||
OUTPUT_DIR = "output"
|
||||
DATA_DIR = "数据快照存储"
|
||||
ARCHIVE_DIR = "压缩包存储"
|
||||
RETAIN_DAYS = 7
|
||||
COMPRESS_FORMAT = "zip"
|
||||
LOG_FILE = os.path.join(OUTPUT_DIR+"data_monitor.log")
|
||||
CHANGES_FILE = os.path.join(OUTPUT_DIR+"changes_summary.csv")
|
||||
MAX_RETRIES = 3
|
||||
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
|
||||
def get_path(*path_parts):
|
||||
return str(Path(*path_parts))
|
||||
|
||||
@staticmethod
|
||||
def ensure_dir(path):
|
||||
Path(path).mkdir(parents=True, exist_ok=True)
|
||||
logger.debug(f"确保目录存在: {path}")
|
||||
|
||||
@staticmethod
|
||||
def get_iso_time():
|
||||
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
|
||||
|
||||
@staticmethod
|
||||
def is_first_run_today():
|
||||
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
snapshot_file = Utils.get_path(Config.OUTPUT_DIR, Config.DATA_DIR, f"snapshot_{today}.csv")
|
||||
widget_file = Utils.get_path(Config.OUTPUT_DIR, Config.DATA_DIR, f"all_widgets_{today}.csv")
|
||||
return not (os.path.exists(snapshot_file) and os.path.exists(widget_file))
|
||||
|
||||
|
||||
# ---------------------- API 客户端 -----------------------
|
||||
class APIClient:
|
||||
def __init__(self):
|
||||
self.headers = {
|
||||
'Authorization': 'Bearer qygHulymo1fekJk4CIZyNKjyQAzG8CFN',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.api = API()
|
||||
|
||||
def request(self, url, payload, method='POST'):
|
||||
for retry in range(Config.MAX_RETRIES + 1):
|
||||
try:
|
||||
response = requests.request(
|
||||
method, url, headers=self.headers,
|
||||
data=payload, timeout=30
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response
|
||||
except requests.exceptions.RequestException as e:
|
||||
if retry == Config.MAX_RETRIES:
|
||||
raise
|
||||
time.sleep(Config.RETRY_DELAY)
|
||||
logger.warning(f"请求失败 (尝试 {retry + 1}/{Config.MAX_RETRIES}): {str(e)}")
|
||||
|
||||
|
||||
# ---------------------- 数据处理类 -----------------------
|
||||
class DataHandler:
|
||||
def __init__(self):
|
||||
self.execution_time = Utils.get_iso_time()
|
||||
self.today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
|
||||
self.setup_dirs()
|
||||
self.api = APIClient()
|
||||
|
||||
def setup_dirs(self):
|
||||
self.data_dir = Utils.get_path(Config.OUTPUT_DIR, Config.DATA_DIR)
|
||||
self.archive_dir = Utils.get_path(Config.OUTPUT_DIR, Config.ARCHIVE_DIR)
|
||||
Utils.ensure_dir(self.data_dir)
|
||||
Utils.ensure_dir(self.archive_dir)
|
||||
self.last_data_file = Utils.get_path(self.data_dir, "last_data.csv")
|
||||
self.last_widget_file = Utils.get_path(self.data_dir, "last_widget_data.csv")
|
||||
|
||||
def load_last_data(self):
|
||||
try:
|
||||
last_data = pd.read_csv(self.last_data_file) if os.path.exists(self.last_data_file) else None
|
||||
last_widget = pd.read_csv(self.last_widget_file) if os.path.exists(self.last_widget_file) else None
|
||||
return last_data, last_widget
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"加载上次数据失败: {str(e)}")
|
||||
return None, None
|
||||
|
||||
def save_last_data(self, data, widget_data):
|
||||
try:
|
||||
data.to_csv(self.last_data_file, index=False)
|
||||
widget_data.to_csv(self.last_widget_file, index=False)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"保存当前数据失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def save_to_csv(self, data, filename):
|
||||
try:
|
||||
temp_file = filename + '.tmp'
|
||||
data.to_csv(temp_file, index=False)
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
os.rename(temp_file, filename)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"保存文件失败: {filename}, 错误: {str(e)}")
|
||||
return False
|
||||
|
||||
|
||||
# ---------------------- 数据监控主类 -----------------------
|
||||
class DataMonitor(DataHandler):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.last_data, self.last_widget = self.load_last_data()
|
||||
|
||||
def fetch_apps(self):
|
||||
url = "https://api.jiandaoyun.com/api/v5/app/list"
|
||||
payload = json.dumps({"skip": 0, "limit": 100})
|
||||
response = self.api.request(url, payload)
|
||||
return pd.DataFrame(response.json().get("apps", []))
|
||||
|
||||
def fetch_entries(self, app_df):
|
||||
url = "https://api.jiandaoyun.com/api/v5/app/entry/list"
|
||||
all_entries = []
|
||||
|
||||
for _, app in app_df.iterrows():
|
||||
payload = json.dumps({"app_id": app['app_id']})
|
||||
response = self.api.request(url, payload)
|
||||
entries = response.json().get("forms", [])
|
||||
|
||||
if entries:
|
||||
entry_df = pd.DataFrame(entries)
|
||||
entry_df['app_id'] = app['app_id']
|
||||
all_entries.append(entry_df)
|
||||
|
||||
return pd.concat(all_entries, ignore_index=True) if all_entries else None
|
||||
|
||||
def fetch_widgets(self, entry_df):
|
||||
url = "https://api.jiandaoyun.com/api/v5/app/entry/widget/list"
|
||||
all_widgets = []
|
||||
|
||||
for _, entry in entry_df.iterrows():
|
||||
payload = json.dumps({
|
||||
"app_id": entry['app_id'],
|
||||
"entry_id": entry['entry_id']
|
||||
})
|
||||
response = self.api.request(url, payload)
|
||||
widgets = response.json().get('widgets', [])
|
||||
|
||||
if widgets:
|
||||
widget_df = pd.DataFrame(widgets)
|
||||
widget_df['app_id'] = entry['app_id']
|
||||
widget_df['entry_id'] = entry['entry_id']
|
||||
all_widgets.append(widget_df)
|
||||
|
||||
return pd.concat(all_widgets, ignore_index=True) if all_widgets else None
|
||||
|
||||
def fetch_monitor_data(self):
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4", "entry_id": "6850c044f17c934b3ec01fea"}
|
||||
data = self.api.api.entry_data_list(payload).get("data")
|
||||
data_list = pd.DataFrame(data)
|
||||
|
||||
for col in data_list.columns:
|
||||
if data_list[col].apply(lambda x: isinstance(x, (dict, list))).any():
|
||||
data_list[col] = data_list[col].astype(str)
|
||||
|
||||
return data_list.drop_duplicates()
|
||||
|
||||
def match_widgets(self, data_list, widget_list):
|
||||
if '_widget_1750122565203' not in data_list.columns:
|
||||
raise ValueError("数据列表中缺少 '_widget_1750122565203' 列")
|
||||
return widget_list[widget_list['entry_id'].isin(data_list['_widget_1750122565203'])]
|
||||
|
||||
def archive_old_data(self):
|
||||
keep_dates = [
|
||||
(datetime.now(timezone.utc) - timedelta(days=i)).strftime("%Y-%m-%d")
|
||||
for i in range(Config.RETAIN_DAYS)
|
||||
]
|
||||
|
||||
files_to_archive = [
|
||||
f for f in os.listdir(self.data_dir)
|
||||
if (f.startswith("snapshot_") or f.startswith("all_widgets_")) and f.endswith(".csv")
|
||||
]
|
||||
|
||||
for filename in files_to_archive:
|
||||
date_str = filename[9:-4] if filename.startswith("snapshot_") else filename[12:-4]
|
||||
|
||||
if date_str not in keep_dates:
|
||||
year_month = date_str[:7]
|
||||
archive_name = Utils.get_path(self.archive_dir, f"snapshots_{year_month}.{Config.COMPRESS_FORMAT}")
|
||||
file_path = Utils.get_path(self.data_dir, filename)
|
||||
|
||||
with zipfile.ZipFile(archive_name, 'a', zipfile.ZIP_DEFLATED) as zipf:
|
||||
zipf.write(file_path, arcname=filename)
|
||||
|
||||
os.remove(file_path)
|
||||
logger.debug(f"已归档 {filename} 到 {archive_name}")
|
||||
|
||||
def compare_data(self, current_data):
|
||||
if not os.path.exists(self.last_data_file):
|
||||
return None
|
||||
|
||||
last_data = pd.read_csv(self.last_data_file)
|
||||
last_data['unique_id'] = last_data['name'].astype(str) + last_data['app_id'].astype(str)
|
||||
current_data['unique_id'] = current_data['name'].astype(str) + current_data['app_id'].astype(str)
|
||||
|
||||
merged = pd.merge(
|
||||
last_data, current_data,
|
||||
on=['unique_id'],
|
||||
how='outer',
|
||||
suffixes=('_last', '_current'),
|
||||
indicator=True
|
||||
)
|
||||
|
||||
changes = {
|
||||
'added': merged[merged['_merge'] == 'right_only'],
|
||||
'deleted': merged[merged['_merge'] == 'left_only'],
|
||||
'modified': pd.DataFrame()
|
||||
}
|
||||
|
||||
for col in ['label', 'type']:
|
||||
last_col = f"{col}_last"
|
||||
current_col = f"{col}_current"
|
||||
|
||||
if last_col in merged.columns and current_col in merged.columns:
|
||||
mask = (merged['_merge'] == 'both') & (merged[last_col] != merged[current_col])
|
||||
mask = mask & ~merged[last_col].isna() & ~merged[current_col].isna()
|
||||
|
||||
if mask.any():
|
||||
modified = merged.loc[mask].copy()
|
||||
modified['changed_field'] = col
|
||||
modified['old_value'] = modified[last_col]
|
||||
modified['new_value'] = modified[current_col]
|
||||
modified['change_status'] = 'update'
|
||||
changes['modified'] = pd.concat([changes['modified'], modified])
|
||||
|
||||
return changes
|
||||
|
||||
def save_changes(self, changes, apps, entries):
|
||||
result_rows = []
|
||||
|
||||
for change_type in ['added', 'deleted', 'modified']:
|
||||
suffix = 'current' if change_type in ['added', 'modified'] else 'last'
|
||||
|
||||
for _, row in changes[change_type].iterrows():
|
||||
app_id = row[f'app_id_{suffix}']
|
||||
entry_id = row[f'entry_id_{suffix}']
|
||||
|
||||
app_name = apps.loc[apps['app_id'] == app_id, 'name'].values[0] if not apps[
|
||||
apps['app_id'] == app_id].empty else '未知应用'
|
||||
entry_name = \
|
||||
entries.loc[(entries['app_id'] == app_id) & (entries['entry_id'] == entry_id), 'name'].values[0] if not \
|
||||
entries[(entries['app_id'] == app_id) & (entries['entry_id'] == entry_id)].empty else '未知表单'
|
||||
|
||||
if change_type == 'added':
|
||||
content = f"新增字段: {row['label_current']}"
|
||||
elif change_type == 'deleted':
|
||||
content = f"删除字段: {row['label_last']}"
|
||||
else:
|
||||
content = f"由\"{row['old_value']}\"修改为\"{row['new_value']}\""
|
||||
|
||||
result_rows.append({
|
||||
'程序执行时间': self.execution_time,
|
||||
'unique_id': row['unique_id'],
|
||||
'app_id': app_id,
|
||||
'app_name': app_name,
|
||||
'entry_id': entry_id,
|
||||
'entry_name': entry_name,
|
||||
'change_type': {'added': '新增', 'deleted': '删除', 'modified': '修改'}[change_type],
|
||||
'具体内容': content
|
||||
})
|
||||
|
||||
if result_rows:
|
||||
result_df = pd.DataFrame(result_rows)
|
||||
changes_file = Utils.get_path(self.data_dir, Config.CHANGES_FILE)
|
||||
result_df.to_csv(changes_file, mode='a', header=not os.path.exists(changes_file), index=False)
|
||||
self.add_to_jiandaoyun(result_df)
|
||||
return True
|
||||
return False
|
||||
|
||||
def add_to_jiandaoyun(self, result_df):
|
||||
all_data = [{
|
||||
"_widget_1751446961315": {"value": row["app_name"]},
|
||||
"_widget_1751446961316": {"value": row["entry_name"]},
|
||||
"_widget_1751446961317": {"value": row["change_type"]},
|
||||
"_widget_1751446961318": {"value": row["具体内容"]},
|
||||
"_widget_1751446961319": {"value": row["程序执行时间"]},
|
||||
} for _, row in result_df.iterrows()]
|
||||
|
||||
payload = {
|
||||
"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6863a402a77925690a470cc5",
|
||||
"data_list": all_data
|
||||
}
|
||||
|
||||
response = self.api.api.entry_data_batch_create(payload)
|
||||
|
||||
if isinstance(response, list):
|
||||
logger.info(f"成功写入 {len(response)} 条变更数据到简道云")
|
||||
return True
|
||||
else:
|
||||
error_task_logger.error(f"写入简道云失败: {response.get('message', '未知错误')}")
|
||||
return False
|
||||
|
||||
def run_daily_snapshot(self):
|
||||
logger.info("=== 开始每日数据快照任务 ===")
|
||||
|
||||
apps = self.fetch_apps()
|
||||
entries = self.fetch_entries(apps)
|
||||
widgets = self.fetch_widgets(entries)
|
||||
monitor_data = self.fetch_monitor_data()
|
||||
matched_data = self.match_widgets(monitor_data, widgets)
|
||||
|
||||
self.save_to_csv(widgets, Utils.get_path(self.data_dir, f"all_widgets_{self.today}.csv"))
|
||||
self.save_to_csv(matched_data, Utils.get_path(self.data_dir, f"snapshot_{self.today}.csv"))
|
||||
self.archive_old_data()
|
||||
self.save_last_data(matched_data, widgets)
|
||||
|
||||
logger.info("=== 每日数据快照任务成功完成 ===")
|
||||
return True
|
||||
|
||||
def run_hourly_check(self):
|
||||
logger.info("=== 开始每小时数据检查任务 ===")
|
||||
|
||||
apps = self.fetch_apps()
|
||||
entries = self.fetch_entries(apps)
|
||||
widgets = self.fetch_widgets(entries)
|
||||
monitor_data = self.fetch_monitor_data()
|
||||
current_data = self.match_widgets(monitor_data, widgets)
|
||||
|
||||
changes = self.compare_data(current_data)
|
||||
if changes and any(len(v) > 0 for v in changes.values()):
|
||||
self.save_changes(changes, apps, entries)
|
||||
|
||||
self.save_last_data(current_data, widgets)
|
||||
|
||||
logger.info("=== 每小时数据检查任务成功完成 ===")
|
||||
return True
|
||||
|
||||
def main(self):
|
||||
import datetime
|
||||
task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
logger.info(f"=== 开始数据监控任务 ({self.execution_time}) ===")
|
||||
|
||||
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, "字段监控")
|
||||
|
||||
logger.info("=== 数据监控任务完成 ===")
|
||||
return success
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
Utils.ensure_dir(Config.OUTPUT_DIR)
|
||||
monitor = DataMonitor()
|
||||
if not monitor.main():
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,72 @@
|
||||
from datetime import date, timedelta, datetime
|
||||
import holidays
|
||||
from config import Config
|
||||
import psycopg2
|
||||
import pandas as pd
|
||||
import pymysql # 使用 pymysql 替代 mysql.connector
|
||||
|
||||
|
||||
class JCB_efficient_car_pickup:
|
||||
def __init__(self):
|
||||
# 使用 pymysql 连接数据库
|
||||
self.conn = pymysql.connect(
|
||||
host=Config.JCB_CONN_host,
|
||||
database=Config.JCB_CONN_INFO_database,
|
||||
user=Config.JCB_CONN_INFO_user,
|
||||
password=Config.JCB_CONN_INFO_password,
|
||||
# charset='utf8mb4', # 设置字符集以避免编码问题
|
||||
# cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
|
||||
)
|
||||
|
||||
def get_jcb_details(self, days_back=1):
|
||||
"""
|
||||
从固定的数据库中获取前几天的NGV明细。
|
||||
参数 `days_back` 表示相对于今天的天数偏移量,默认为1(即前一天)。
|
||||
返回包含NGV明细的pandas DataFrame。
|
||||
"""
|
||||
try:
|
||||
# 获得连接并创建游标
|
||||
cursor = self.conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
# now_time = datetime.now()
|
||||
# target_time = now_time + timedelta(days=-days_back)
|
||||
target_date_id = "接车宝" # 获取目标日期
|
||||
|
||||
# SQL 查询语句
|
||||
sql = f"""
|
||||
SELECT * FROM jdy_hs_holo_dws_sales_magic_box_ngv_d WHERE 产品名称 = '{target_date_id}';
|
||||
"""
|
||||
|
||||
# 执行查询并获取结果
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall() # pymysql 的 DictCursor 会返回字典列表
|
||||
|
||||
# 将结果转换为 DataFrame
|
||||
if rows: # 如果有数据
|
||||
data_NGV = pd.DataFrame(rows)
|
||||
else: # 如果没有数据,返回空 DataFrame
|
||||
data_NGV = pd.DataFrame()
|
||||
|
||||
# 尝试自动解析日期时间字符串
|
||||
time_format = "%Y-%m-%d %H:%M:%S"
|
||||
if 'saas_create_time' in data_NGV.columns:
|
||||
data_NGV['saas_create_time'] = pd.to_datetime(data_NGV['saas_create_time'], format=time_format,
|
||||
errors='coerce')
|
||||
data_NGV['saas_create_time'] = data_NGV['saas_create_time'].dt.strftime('%Y-%m-%d')
|
||||
|
||||
# 关闭游标
|
||||
cursor.close()
|
||||
|
||||
return data_NGV
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start = JCB_efficient_car_pickup()
|
||||
result = start.get_jcb_details(days_back=1)
|
||||
if result is not None:
|
||||
print(result.head()) # 打印前几行数据
|
||||
@@ -0,0 +1,53 @@
|
||||
from datetime import date, timedelta, datetime
|
||||
import holidays
|
||||
from config import Config
|
||||
import psycopg2
|
||||
import pandas as pd
|
||||
|
||||
class GetProvateMiniProgram(Config):
|
||||
def get_private_mini_program_details(self, days_back=1):
|
||||
"""
|
||||
从固定的数据库中获取前几天的NGV明细。
|
||||
参数 `days_back` 表示相对于今天的天数偏移量,默认为1(即前一天)。
|
||||
返回包含NGV明细的pandas DataFrame。
|
||||
"""
|
||||
try:
|
||||
# 获得连接
|
||||
conn = psycopg2.connect(**self.conn)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取指定天数前的日期
|
||||
now_time = datetime.now()
|
||||
target_time = now_time + timedelta(days=-days_back)
|
||||
target_date_id = int(target_time.strftime('%Y%m%d')) # 获取目标日期
|
||||
|
||||
# sql语句查询
|
||||
sql = f"""
|
||||
SELECT * FROM "public"."holo_ads_report_saas_profile_ngv_detail_d" WHERE "date_id" = '{target_date_id}' ;
|
||||
"""
|
||||
|
||||
# 执行语句并获取结果集
|
||||
cursor.execute(sql)
|
||||
rows = cursor.fetchall()
|
||||
all_fields = cursor.description
|
||||
|
||||
# 执行结果转化为dataframe
|
||||
col = [i[0] for i in all_fields]
|
||||
data_NGV = pd.DataFrame(rows, columns=col)
|
||||
|
||||
# 尝试自动解析日期时间字符串
|
||||
time_format = "%Y-%m-%d %H:%M:%S"
|
||||
if 'saas_create_time' in data_NGV.columns:
|
||||
data_NGV['saas_create_time'] = pd.to_datetime(data_NGV['saas_create_time'], format=time_format,
|
||||
errors='coerce')
|
||||
data_NGV['saas_create_time'] = data_NGV['saas_create_time'].dt.strftime('%Y-%m-%d')
|
||||
|
||||
# 关闭游标和连接
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
return data_NGV
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
return None
|
||||
@@ -0,0 +1,387 @@
|
||||
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
|
||||
|
||||
common_module = CommonModule()
|
||||
|
||||
# 初始化 API 实例和 Token
|
||||
api_instance = YDAPI()
|
||||
TOKEN = api_instance.generateToken()
|
||||
|
||||
FORMID = "FORM-XHA66881FHMAR0F07GT4Y59GGA972DD6B5OHLB"
|
||||
appType = "APP_RTPWHV37ENXPQUZHTL25"
|
||||
systemToken = "IA766O61SHFZT6UB0WNOB58GI5RW2K58KCU1LL6"
|
||||
|
||||
|
||||
class TimeConsumingProcess():
|
||||
"""
|
||||
获取流程表单数据耗时
|
||||
"""
|
||||
|
||||
def fetch_process_data(self):
|
||||
"""获取所有流程实例"""
|
||||
today_midnight = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
yesterday_midnight = today_midnight - timedelta(days=1)
|
||||
|
||||
start_time = yesterday_midnight.strftime("%Y-%m-%d") # 昨天0点
|
||||
end_time = today_midnight.strftime("%Y-%m-%d") # 今天0点
|
||||
form_data_two = api_instance.read_processes_instances(
|
||||
token=TOKEN, formUuid=FORMID, page=1, n=100,
|
||||
appType=appType, systemToken=systemToken, instanceStatus="",
|
||||
createFromTimeGMT=start_time, createToTimeGMT=end_time
|
||||
) # 之后添加增量更新
|
||||
|
||||
all_process_list = []
|
||||
|
||||
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(
|
||||
token=TOKEN, formUuid=FORMID, page=a, n=100,
|
||||
appType=appType, systemToken=systemToken, instanceStatus="",
|
||||
createFromTimeGMT=start_time, createToTimeGMT=end_time
|
||||
)
|
||||
all_process_list = all_process_list + form_data_two.get("data")
|
||||
except Exception as e:
|
||||
print(f"Error fetching page {a}: {e}")
|
||||
continue
|
||||
|
||||
return all_process_list
|
||||
|
||||
def extract_approval_records(self, process_instances):
|
||||
"""提取每条流程的审批记录"""
|
||||
all_data_list = []
|
||||
for data in tqdm(process_instances, desc="处理流程实例"):
|
||||
processInstanceId = data.get("processInstanceId")
|
||||
version = data.get("version")
|
||||
|
||||
res_new = api_instance.get_approval_records(
|
||||
token=TOKEN, processInstanceId=processInstanceId,
|
||||
appType=appType, systemToken=systemToken
|
||||
)
|
||||
records_new = res_new.get('result', [])
|
||||
for record in records_new:
|
||||
operateTimeGMT = record.get('operateTimeGMT')
|
||||
# if operateTimeGMT is not None:
|
||||
# operateTime = datetime.fromtimestamp(operateTimeGMT / 1000).strftime('%Y-%m-%d %H:%M:%S')
|
||||
# else:
|
||||
# operateTime = operateTimeGMT
|
||||
showName = record.get('showName')
|
||||
operatorName = record.get('operatorName')
|
||||
action = record.get('action')
|
||||
# data_id = record.get('dataId')
|
||||
activity_id = record.get('activityId')
|
||||
all_data_list.append(
|
||||
[operateTimeGMT, showName, operatorName, action, processInstanceId, version, activity_id])
|
||||
|
||||
df = pd.DataFrame(all_data_list)
|
||||
# df.to_csv("审批记录.csv", index=False)
|
||||
|
||||
return all_data_list
|
||||
|
||||
def group_by_process(self, all_data_list):
|
||||
"""按 '提交申请' 分组,一个流程为一组"""
|
||||
result_groups = []
|
||||
current_group = []
|
||||
j = 1
|
||||
for record in all_data_list:
|
||||
showName = record[1]
|
||||
if showName == "提交申请":
|
||||
record.append(0)
|
||||
j = 1
|
||||
if current_group:
|
||||
result_groups.append(current_group)
|
||||
current_group = []
|
||||
current_group.append(record)
|
||||
else:
|
||||
record.append(j)
|
||||
j += 1
|
||||
current_group.append(record)
|
||||
if current_group:
|
||||
result_groups.append(current_group)
|
||||
return result_groups
|
||||
|
||||
def transform_to_wide_table(self, result_groups):
|
||||
"""将审批记录从长表转为宽表"""
|
||||
flattened_rows = []
|
||||
|
||||
for group in result_groups:
|
||||
row_data = {}
|
||||
|
||||
# 遍历其余审批节点
|
||||
for i, item in enumerate(group, start=1):
|
||||
operateTimeGMT, showName, operatorName, action, dataId, version, activity_id, index, = item
|
||||
if action == "已撤销":
|
||||
showName = "该节点已撤销"
|
||||
row_data.update({
|
||||
f'审批{i}时间': operateTimeGMT,
|
||||
f'审批{i}节点名': showName,
|
||||
f'审批{i}人': operatorName,
|
||||
f'审批{i}动作': action,
|
||||
f'序号{i}': index,
|
||||
f'审批{i}数据id': dataId,
|
||||
f'审批{i}流程版本': version,
|
||||
f'审批{i}流程节点id': activity_id
|
||||
})
|
||||
|
||||
flattened_rows.append(row_data)
|
||||
|
||||
# 转换为DataFrame
|
||||
df_final = pd.DataFrame(flattened_rows)
|
||||
|
||||
# 计算最大审批步骤
|
||||
max_steps = max(len(group) - 1 for group in result_groups) # 减去提交节点
|
||||
|
||||
# 构建所有列名
|
||||
all_columns = [
|
||||
'审批时间', '审批节点名', '审批人', '审批动作', '序号', '数据id', '流程版本', '流程节点id'
|
||||
]
|
||||
for i in range(1, max_steps + 1):
|
||||
all_columns.extend([
|
||||
f'审批{i}时间',
|
||||
f'审批{i}节点名',
|
||||
f'审批{i}人',
|
||||
f'审批{i}动作',
|
||||
f'序号{i}',
|
||||
f'审批{i}数据id',
|
||||
f'审批{i}流程版本',
|
||||
f'审批{i}流程节点id'
|
||||
])
|
||||
|
||||
# 统一列结构并填充缺失值
|
||||
df_final = df_final.reindex(columns=all_columns)
|
||||
# number填充为0string填充为-
|
||||
numeric_cols = df_final.select_dtypes(include=['number']).columns
|
||||
str_cols = df_final.select_dtypes(include=['object']).columns
|
||||
|
||||
df_final[numeric_cols] = df_final[numeric_cols].fillna(0)
|
||||
df_final[str_cols] = df_final[str_cols].fillna("-")
|
||||
df_final = df_final[df_final['审批时间'].notna()]
|
||||
|
||||
# 导出CSV
|
||||
# df_final.to_csv("审批流程行转列结果_with_node_name.csv", index=False)
|
||||
|
||||
return df_final, max_steps
|
||||
|
||||
def classify_flows(self, df_final, max_steps):
|
||||
"""根据审批节点名 + 动作组合进行流程分组"""
|
||||
|
||||
def extract_signature(row):
|
||||
signature = []
|
||||
i = 1
|
||||
while f'审批{i}节点名' in row:
|
||||
node_name = row[f'审批{i}节点名']
|
||||
action = row[f'审批{i}动作']
|
||||
if node_name == "-":
|
||||
break
|
||||
signature.append((node_name, action))
|
||||
i += 1
|
||||
return signature
|
||||
|
||||
def has_special_action(signature):
|
||||
special_actions = {"已撤销", "已转交", "已退回", "已拒绝"}
|
||||
for _, action in signature:
|
||||
if action in special_actions:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_hash(signature):
|
||||
sig_str = str(signature)
|
||||
return hashlib.md5(sig_str.encode('utf-8')).hexdigest()
|
||||
|
||||
df_final['signature'] = df_final.apply(extract_signature, axis=1)
|
||||
|
||||
group_map = {}
|
||||
current_group_id = 1
|
||||
df_final['group_id'] = 0
|
||||
|
||||
for idx, row in df_final.iterrows():
|
||||
sig = row['signature']
|
||||
if has_special_action(sig):
|
||||
df_final.at[idx, 'group_id'] = 5000
|
||||
# current_group_id += 1
|
||||
else:
|
||||
sig_hash = get_hash(sig)
|
||||
if sig_hash not in group_map:
|
||||
group_map[sig_hash] = current_group_id
|
||||
current_group_id += 1
|
||||
df_final.at[idx, 'group_id'] = group_map[sig_hash]
|
||||
|
||||
# df_final.to_csv("审批流程分类结果.csv", index=False)
|
||||
# print("✅ 分组完成,已保存至 '审批流程分类结果.csv'")
|
||||
|
||||
result_rows = []
|
||||
for index, row in df_final.iterrows():
|
||||
base_info = {'group_id': row["group_id"]}
|
||||
process_id_list = []
|
||||
process_list = []
|
||||
for i in range(1, max_steps):
|
||||
prefix = f'审批{i}'
|
||||
if row[f'{prefix}流程节点id'] != "-":
|
||||
process_id = row[f'{prefix}流程节点id']
|
||||
process_id_list.append(process_id)
|
||||
if row[f'{prefix}节点名'] != "-":
|
||||
process = row[f'{prefix}节点名']
|
||||
process_list.append(process)
|
||||
|
||||
for i in range(1, max_steps): # 审批1到审批n
|
||||
prefix = f'审批{i}'
|
||||
approval_data = {}
|
||||
if f'{prefix}时间' in df_final.columns and pd.notna(row[f'{prefix}时间']) and row[
|
||||
f'{prefix}时间'] != '-':
|
||||
approval_data = {
|
||||
'审批时间': row[f'{prefix}时间'],
|
||||
'审批节点名': row[f'{prefix}节点名'],
|
||||
'审批人': row[f'{prefix}人'],
|
||||
'审批动作': row[f'{prefix}动作'],
|
||||
'序号': row[f'序号{i}'] if f'序号{i}' in df_final.columns else '-',
|
||||
f'审批数据id': row[f'审批{i}数据id'] if f'审批{i}数据id' in df_final.columns else '-',
|
||||
f'审批流程版本': row[f'审批{i}流程版本'] if f'审批{i}流程版本' in df_final.columns else '-',
|
||||
f'审批流程节点id': row[
|
||||
f'审批{i}流程节点id'] if f'审批{i}流程节点id' in df_final.columns else '-',
|
||||
f'审批节点id合并': process_id_list,
|
||||
f'审批节点名合并': process_list
|
||||
}
|
||||
# 合并基础数据和审批数据
|
||||
result_row = {**base_info, **approval_data}
|
||||
result_rows.append(result_row)
|
||||
dfn = pd.DataFrame(result_rows)
|
||||
|
||||
# dfn.to_csv("审批流程分类结果_with_node_name.csv", index=False)
|
||||
|
||||
return dfn
|
||||
|
||||
def time_calculate(self, df_final):
|
||||
"""计算每个审批步骤之间的耗时(秒),并设置"提交申请"的耗时为0"""
|
||||
# 创建副本避免SettingWithCopyWarning
|
||||
df_final = df_final.copy()
|
||||
|
||||
# 确保审批时间为 datetime 类型
|
||||
df_final["审批时间"] = pd.to_datetime(df_final["审批时间"])
|
||||
|
||||
# 处理空值(修复FutureWarning)
|
||||
numeric_cols = df_final.select_dtypes(include=['number']).columns
|
||||
df_final[numeric_cols] = df_final[numeric_cols].fillna(0)
|
||||
str_cols = df_final.select_dtypes(include=['object']).columns
|
||||
df_final[str_cols] = df_final[str_cols].fillna("-")
|
||||
|
||||
# 处理JSON列(修复其他SettingWithCopyWarning)
|
||||
df_final.loc[:, '审批节点id合并'] = df_final['审批节点id合并'].apply(
|
||||
lambda x: json.dumps(x, ensure_ascii=False) if isinstance(x, (list, dict)) else x
|
||||
)
|
||||
df_final.loc[:, '审批节点名合并'] = df_final['审批节点名合并'].apply(
|
||||
lambda x: json.dumps(x, ensure_ascii=False) if isinstance(x, (list, dict)) else x
|
||||
)
|
||||
|
||||
# 计算耗时
|
||||
df_final.loc[:, '耗时'] = df_final['审批时间'].diff().dt.total_seconds().div(60)
|
||||
df_final.loc[df_final['审批动作'] == '提交申请', '耗时'] = 0
|
||||
df_final['耗时'] = df_final['耗时'].fillna(0)
|
||||
|
||||
# 处理时间转换(修复第一个SettingWithCopyWarning)
|
||||
df_final.loc[:, "审批时间"] = pd.to_datetime(df_final["审批时间"]).dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 拼接url
|
||||
df_final[
|
||||
"url"] = "https://f6car.aliwork.com/APP_RTPWHV37ENXPQUZHTL25/formDetail/FORM-XHA66881FHMAR0F07GT4Y59GGA972DD6B5OHLB?formInstId=" + \
|
||||
df_final["审批数据id"].astype(str)
|
||||
return df_final
|
||||
|
||||
def write_to_bi(self, df_final):
|
||||
# 连接信息
|
||||
|
||||
table_name = "yida_process_time_statistics"
|
||||
|
||||
# 连接数据库
|
||||
connection = mysql.connector.connect(
|
||||
host=Config.BI_CONN_host,
|
||||
user=Config.BI_CONN_INFO_user,
|
||||
password=Config.BI_CONN_INFO_password,
|
||||
database=Config.BI_CONN_INFO_database
|
||||
)
|
||||
print(f"成功连接 {Config.BI_CONN_INFO_database}")
|
||||
cursor = connection.cursor()
|
||||
|
||||
# 数据预处理
|
||||
df = df_final.copy()
|
||||
|
||||
# 1. 转换时间戳为字符串
|
||||
for col in df.select_dtypes(include=['datetime64[ns]', 'datetimetz']).columns:
|
||||
df[col] = pd.to_datetime(df[col]).dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 2. 增强空值处理(包含更多可能的空值表示)
|
||||
empty_values = [np.nan, None, '', 'null', 'NULL', 'NA', 'NaN', 'None', '-']
|
||||
df = df.replace(empty_values, None)
|
||||
|
||||
# 3. 严格过滤条件(确保所有关键字段都有有效值)
|
||||
required_columns = ['审批节点名', '审批时间', 'group_id', '审批人', '审批动作']
|
||||
df = df.dropna(subset=required_columns, how='any')
|
||||
|
||||
# 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)
|
||||
placeholders = ', '.join(['%s'] * len(df.columns))
|
||||
insert_query = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
|
||||
|
||||
# 批量插入数据
|
||||
records = [tuple(row) for row in df.values]
|
||||
cursor.executemany(insert_query, records)
|
||||
connection.commit()
|
||||
print(f"成功导入 {cursor.rowcount} 条记录到 {table_name} 表")
|
||||
|
||||
except Exception as e:
|
||||
connection.rollback()
|
||||
print(f"写入失败: {str(e)}")
|
||||
# 打印前5条问题数据
|
||||
print("问题数据示例:")
|
||||
print(df.head().to_string())
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
def main(self):
|
||||
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
# Step 1: 获取流程实例
|
||||
process_instances = self.fetch_process_data()
|
||||
|
||||
# Step 2: 提取审批记录
|
||||
all_data_list = self.extract_approval_records(process_instances)
|
||||
|
||||
# Step 3: 按 '提交申请' 分组
|
||||
result_groups = self.group_by_process(all_data_list)
|
||||
|
||||
# Step 4: 转换为宽表
|
||||
df_final, max_steps = self.transform_to_wide_table(result_groups)
|
||||
|
||||
# Step 5: 对流程进行分类并保存结果
|
||||
df_final1 = self.classify_flows(df_final, max_steps)
|
||||
|
||||
# Step 6: 耗时计算
|
||||
df_final2 = self.time_calculate(df_final1)
|
||||
|
||||
# Step 7: 向BI写入数据
|
||||
self.write_to_bi(df_final2)
|
||||
|
||||
common_module.send_task_status(task_start_time, "宜搭流程耗时写入BI")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = TimeConsumingProcess()
|
||||
start.main()
|
||||
@@ -0,0 +1,191 @@
|
||||
# -*- 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
|
||||
from tqdm import tqdm
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
|
||||
|
||||
class ImportPerformanceData:
|
||||
"""
|
||||
履约表数据支撑
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.staff_name_to_id = None
|
||||
self.staff_id_list = None
|
||||
self.performance_data_list = None
|
||||
self.field_mapping = {}
|
||||
self.fields()
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有数据"""
|
||||
payload = {"api_key": "675b900991ad2491c69389ca",
|
||||
"entry_id": "68637c9818bc333fc14c30ad", # 需要修改
|
||||
}
|
||||
performance_data = api_instance.entry_data_list(payload)
|
||||
self.performance_data_list = performance_data.get("data") # 履约表
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 预处理员工姓名到ID的映射
|
||||
self.staff_name_to_id = {
|
||||
str(item["_widget_1734942794144"]): item["_widget_1734942794145"]
|
||||
for item in self.staff_id_list
|
||||
}
|
||||
|
||||
def process_data(self, df):
|
||||
"""处理数据的主函数"""
|
||||
new_df = self.convert_to_utc(df)
|
||||
all_data = []
|
||||
|
||||
# 预定义角色映射
|
||||
role_mapping = {
|
||||
'运营负责人': '运营负责人',
|
||||
'区域经理': '区域经理'
|
||||
}
|
||||
|
||||
# 使用iterrows的替代方案itertuples更快,但需要确保列名是有效的Python标识符
|
||||
for row in tqdm(new_df.itertuples(index=False), total=len(new_df)):
|
||||
row_dict = row._asdict()
|
||||
|
||||
# 成员字段替换
|
||||
for role, field in role_mapping.items():
|
||||
name = getattr(row, field, None)
|
||||
if name and str(name) in self.staff_name_to_id:
|
||||
row_dict[role] = self.staff_name_to_id[str(name)]
|
||||
else:
|
||||
row_dict[role] = None
|
||||
|
||||
# 简道云字段替换
|
||||
data_dict = self.row_to_dict(row_dict, self.field_mapping)
|
||||
all_data.append(data_dict)
|
||||
|
||||
return all_data
|
||||
|
||||
def convert_to_utc(self, df):
|
||||
# 创建副本避免修改原DataFrame
|
||||
new_df = df.copy()
|
||||
time_columns = ['saas开户时间', '服务期起始时间', '下单支付成功时间', '操作时间',
|
||||
"下单支付成功日期", "服务期结束时间"]
|
||||
|
||||
for col in tqdm(time_columns):
|
||||
if col in tqdm(new_df.columns): # 安全检查列是否存在
|
||||
try:
|
||||
# 1. 转换为datetime(自动推断格式,处理无效值为NaT)
|
||||
new_df[col] = pd.to_datetime(new_df[col], errors='coerce', utc=False)
|
||||
|
||||
# 2. 时区转换(仅对有效日期操作)
|
||||
mask = new_df[col].notna() # 只处理非空值
|
||||
if mask.any(): # 如果有有效日期才转换
|
||||
# 本地化为北京时间,然后转换为UTC
|
||||
new_df.loc[mask, col + '_utc'] = (
|
||||
new_df.loc[mask, col]
|
||||
.dt.tz_localize('Asia/Shanghai', ambiguous='infer', nonexistent='shift_forward')
|
||||
.dt.tz_convert('UTC')
|
||||
.dt.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
)
|
||||
else:
|
||||
new_df[col + '_utc'] = pd.NA # 全部为空时保持一致性
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理列 {col} 时出错: {str(e)}")
|
||||
new_df[col + '_utc'] = pd.NA # 出错时设为NA
|
||||
|
||||
return new_df
|
||||
|
||||
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)
|
||||
|
||||
print("数据获取完成")
|
||||
|
||||
# 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)
|
||||
print("数据删除完成")
|
||||
|
||||
# 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)
|
||||
|
||||
print("数据写入完成")
|
||||
common_module.send_task_status(task_start_time, "履约表数据支撑")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
# 处理Timestamp类型
|
||||
if pd.isna(value):
|
||||
clean_value = None
|
||||
elif isinstance(value, pd.Timestamp):
|
||||
clean_value = value.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
else:
|
||||
clean_value = value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = {
|
||||
'公司名称': '_widget_1751350424090', '门店名称': '_widget_1751350424083',
|
||||
'门店编码': '_widget_1751350424084',
|
||||
'运营负责人': '_widget_1751350424085', '区域经理': '_widget_1751350424086',
|
||||
'saas开户时间': '_widget_1751350424088', '服务期起始时间': '_widget_1751350424097',
|
||||
'下单支付成功时间': '_widget_1751350424101', '操作时间': '_widget_1751350424110',
|
||||
'下单支付成功日期': '_widget_1751350424115', '服务期结束时间': '_widget_1751350424098',
|
||||
'订单id': '_widget_1751350424075', 'f6订单编号': '_widget_1751350424076',
|
||||
'宜搭的实例id': '_widget_1751350424077', '商品id': '_widget_1751350424078',
|
||||
'商品名称': '_widget_1751350424079', '发布商品类型': '_widget_1751350424080',
|
||||
'发布商品类型描述': '_widget_1751350424081', '门店id': '_widget_1751350424082',
|
||||
'商户中心id': '_widget_1751350424087', '公司id': '_widget_1751350424089',
|
||||
'产生来源': '_widget_1751350424091', '产生来源描述': '_widget_1751350424092',
|
||||
'类型': '_widget_1751350424093', '类型描述': '_widget_1751350424094', '服务年份': '_widget_1751350424095',
|
||||
'订单服务期第几年': '_widget_1751350424096', '提成业务类型': '_widget_1751350424099',
|
||||
'提成类别': '_widget_1751350424100', '实付金额': '_widget_1751881109632',
|
||||
'系统成本价': '_widget_1751881109633', '版本费': '_widget_1751881109634',
|
||||
'服务费': '_widget_1751881109635', '介绍人员工ID': '_widget_1751350424106',
|
||||
'介绍业绩归属人员工ID': '_widget_1751350424107', '处理人ID employee_id': '_widget_1751350424108',
|
||||
'业绩归属人员工ID': '_widget_1751350424109', '处理人是否跟进,0: 未跟进,1: 已跟进': '_widget_1751350424111',
|
||||
'满意度评分': '_widget_1751350424112', '评价完成时间': '_widget_1751350424113',
|
||||
'介绍人用户类型': '_widget_1751350424114', '培训完成时间': '_widget_1751350424116',
|
||||
'订单所处阶段': '_widget_1751350424117', '日分区': '_widget_1751350424118',
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = ImportPerformanceData()
|
||||
start.main()
|
||||
@@ -0,0 +1,149 @@
|
||||
from api import API
|
||||
from back_ground_module import CommonModule
|
||||
import datetime
|
||||
import pandas as pd
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
start_time = datetime.datetime.now()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class InstallEventDispatcher:
|
||||
"""安装服务历史派发"""
|
||||
|
||||
def __init__(self):
|
||||
# 直接在初始化时设置映射关系
|
||||
self.services_list = None
|
||||
self.reversed_field_mapping = {
|
||||
"省": "_widget_1750301534569",
|
||||
"市": "_widget_1750301534570",
|
||||
"区": "_widget_1750301534571",
|
||||
"门店名称": "_widget_1750301534572",
|
||||
"门店id": "_widget_1750301534573",
|
||||
"负责人": "_widget_1750301534574",
|
||||
"联系电话": "_widget_1750301534575",
|
||||
"线索状态": "_widget_1750301534577",
|
||||
"线索来源": "_widget_1750301534576",
|
||||
}
|
||||
|
||||
self.field_mapping = {
|
||||
"省": "_widget_1744177321450",
|
||||
"市": "_widget_1744182647145",
|
||||
"区": "_widget_1744182647146",
|
||||
"门店名称": "_widget_1744177321449",
|
||||
"门店id": "_widget_1744177321451",
|
||||
"负责人": "_widget_1744177321452",
|
||||
"联系电话": "_widget_1744177321453",
|
||||
"线索来源": "_widget_1744187212674",
|
||||
}
|
||||
|
||||
self.install_service_lead = None
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 安装服务线索池
|
||||
payload = {"api_key": "66f3a68c6e56814df2c6b1af", "entry_id": "68537b5e60a6295c6c09b464"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.install_service_lead = json_dict.get("data")
|
||||
|
||||
# 安装服务客服表
|
||||
payload = {"api_key": "66f3a68c6e56814df2c6b1af", "entry_id": "6809d4ef063ece5c83fc61ad"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.services_list = json_dict.get("data")
|
||||
|
||||
def row_to_dict(self, row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def reversed_dict(self, old_dict, field_mapping):
|
||||
"""将字段ID映射回中文名称"""
|
||||
id_to_name = {v: k for k, v in field_mapping.items()}
|
||||
new_dict = {}
|
||||
for old_key, value in old_dict.items():
|
||||
# 使用get方法实现高效查找,未找到时保留原键
|
||||
new_key = id_to_name.get(old_key, old_key)
|
||||
new_dict[new_key] = value
|
||||
return new_dict
|
||||
|
||||
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
|
||||
|
||||
# 将list的字段映射为中文
|
||||
new_sign_abnormal_data = [
|
||||
self.reversed_dict(old_dict, self.reversed_field_mapping)
|
||||
for old_dict in install_service_lead_list
|
||||
]
|
||||
|
||||
# 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
|
||||
|
||||
# 3.数据准备
|
||||
new_sign_abnormal_data = [item for item in new_sign_abnormal_data if item["线索状态"] != "已派发"]
|
||||
|
||||
# 截取今日需要派发的数据
|
||||
new_sign_abnormal_data = new_sign_abnormal_data[:count]
|
||||
|
||||
# 获取今日要派发数据的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]
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
api_instance.data_batch_create(data)
|
||||
|
||||
i += 1
|
||||
|
||||
# 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, "安装服务历史派发")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
install_event_dispatcher = InstallEventDispatcher()
|
||||
install_event_dispatcher.main()
|
||||
@@ -0,0 +1 @@
|
||||
2025-08-08 11:36:30,090 - error_task_logger - ERROR - 数据处理完成
|
||||
@@ -0,0 +1,2 @@
|
||||
2025-08-08 11:36:30,090 - task_logger - INFO - 数据处理完成
|
||||
2025-08-08 11:36:30,210 - task_logger - INFO - 任务状态发送成功: {'data': {'creator': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'updater': {'name': 'F6汽车科技', 'username': '#admin', 'status': 1, 'type': 0}, 'deleter': None, 'createTime': '2025-08-08T03:36:29.601Z', 'updateTime': '2025-08-08T03:36:29.601Z', 'deleteTime': None, '_widget_1744873387500': '2025-08-08T00:00:00.000Z', '_widget_1743644977694': '经销商新签服务单转BI', '_widget_1744873387501': '2025-08-08T03:36:29.000Z', '_widget_1744873387502': '2025-08-08T03:36:30.000Z', '_widget_1744873387504': '1', '_id': '689570bd4d37fe546faea135', 'appId': '6694d3c4fcb69ca9a111a6c4', 'entryId': '67ede908eb9c22261016466e'}}
|
||||
@@ -0,0 +1,219 @@
|
||||
# -*- 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
|
||||
import pandas as pd
|
||||
import json
|
||||
import numpy as np
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
# 保存为CSV文件
|
||||
output_dir = "output" # 设置输出目录
|
||||
|
||||
# 创建输出目录(如果不存在)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
|
||||
class NewDealerServiceOrderToBI:
|
||||
# 经销商新签服务单转BI
|
||||
def __init__(self):
|
||||
self.dealer_service_data = None
|
||||
self.field_mapping = {'购买的产品名称': '_widget_1742197585104', '经销商名称': '_widget_1741164213155',
|
||||
'经销商简称': '_widget_1741164213151', '负责人姓名': '_widget_1741165503706',
|
||||
'负责人手机号': '_widget_1741165503711', '经销商可使用的群数量': '_widget_1741165503710',
|
||||
'订单编码': '_widget_1741164213149', '订单支付时间': '_widget_1741164213159',
|
||||
'商户门店ID': '_widget_1741164213152', '开通时间': '_widget_1741164213171',
|
||||
'详细地址': '_widget_1741164213172', '联系电话': '_widget_1741165503708',
|
||||
'系统到期时间': '_widget_1741165503709', '开通状态': '_widget_1741165503714',
|
||||
'销售负责人': '_widget_1741165503716', '运营顾问': '_widget_1741165503718',
|
||||
'运营专家': '_widget_1741165503719', '区域经理': '_widget_1741165503717',
|
||||
'业务人员': '_widget_1741165503721', '是否设置经营范围': '_widget_1742200372555',
|
||||
'不设置经营范围原因': '_widget_1742268351775', '是否建群': '_widget_1742200372553',
|
||||
'不建群原因': '_widget_1742268351776', '是否设置备货清单': '_widget_1742200372634',
|
||||
'不设置备货清单原因': '_widget_1742268351778', '是否设置报价': '_widget_1742260928184',
|
||||
'不设置报价原因': '_widget_1742268351777', '是否上货': '_widget_1742200372559',
|
||||
'不上货原因': '_widget_1742268351779', '是否培训系统使用': '_widget_1749717287367',
|
||||
'不培训系统使用原因': '_widget_1749717287369', '是否补货': '_widget_1749717287373',
|
||||
'不补货原因': '_widget_1749717287375',
|
||||
'是否进行滞销回抽+盘点介绍': '_widget_1742200372561',
|
||||
'不进行滞销回抽+盘点介绍原因': '_widget_1742268351780',
|
||||
'服务是否满意': '_widget_1743148999298', '服务不满意原因': '_widget_1743148999308',
|
||||
'产品是否满意': '_widget_1743148999300', '产品不满意原因': '_widget_1743148999309',
|
||||
# '上传评价图片': '_widget_1743148999310',
|
||||
'培训完成时间':'_widget_1754472835261',
|
||||
'审核备注': '_widget_1743500862664',
|
||||
'完成日期时间': '_widget_1753162835213', '流水号': '_widget_1753163217437',
|
||||
'提交人': 'creator', '提交时间': 'createTime', '更新时间': 'updateTime'}
|
||||
|
||||
def load_all_data(self):
|
||||
# 获取经销商新签服务单数据
|
||||
payload = {"api_key": "673d8427549d00c3d753c530",
|
||||
"entry_id": "67c80eb3d2af9b9821928f45",
|
||||
}
|
||||
dealer_service = api_instance.entry_data_list(payload)
|
||||
self.dealer_service_data = dealer_service.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
def data_process(self):
|
||||
df = pd.DataFrame(self.dealer_service_data)
|
||||
# 反转映射字典
|
||||
reverse_mapping = {v: k for k, v in self.field_mapping.items()}
|
||||
# 1.列明替换
|
||||
df.columns = [reverse_mapping.get(col, col) for col in df.columns]
|
||||
|
||||
# 2.成员字段取值
|
||||
user_columns = ["提交人", "销售负责人", "区域经理", "业务人员", "运营顾问", "运营专家"]
|
||||
|
||||
for col in user_columns:
|
||||
df[col] = df[col].map(lambda x: x.get("name", "") if isinstance(x, dict) else "")
|
||||
|
||||
# 3.日期字段转为北京时间
|
||||
time_columns = ["订单支付时间", "开通时间", "系统到期时间", "完成日期时间", "提交时间", "更新时间","培训完成时间"]
|
||||
|
||||
df[time_columns] = df[time_columns].apply(
|
||||
lambda col: pd.to_datetime(col, errors='coerce')
|
||||
.dt.tz_localize(None)
|
||||
.dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
)
|
||||
|
||||
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" # 替换为你的实际表名
|
||||
|
||||
# 建立数据库连接
|
||||
connection = mysql.connector.connect(
|
||||
host=HS_DB_Config["host"],
|
||||
user=HS_DB_Config["user"],
|
||||
password=HS_DB_Config["password"],
|
||||
database=HS_DB_Config["database"]
|
||||
)
|
||||
cursor = connection.cursor()
|
||||
|
||||
try:
|
||||
# 查询表列名
|
||||
cursor.execute(f"SHOW COLUMNS FROM {table_name}")
|
||||
columns_info = cursor.fetchall()
|
||||
db_columns = [col[0] for col in columns_info] # 提取列名
|
||||
df = df.replace([None, np.nan, pd.NA, 'nan', 'NaN', 'NAN', ''], None)
|
||||
# 保留 DataFrame 中与数据库列名匹配的列
|
||||
filtered_df = df[df.columns.intersection(db_columns)]
|
||||
|
||||
# 如果没有匹配的列,直接返回
|
||||
if filtered_df.empty:
|
||||
print("DataFrame 中没有与数据库表结构匹配的列。")
|
||||
return
|
||||
|
||||
# 筛选列之后,插入前处理 dict 类型
|
||||
filtered_df = filtered_df.copy()
|
||||
for col in filtered_df.columns:
|
||||
if filtered_df[col].apply(lambda x: isinstance(x, (dict, list)) if x is not None else False).any():
|
||||
filtered_df.loc[:, col] = filtered_df[col].apply(
|
||||
lambda x: json.dumps(x, ensure_ascii=False) if x is not None else x
|
||||
)
|
||||
|
||||
# 构建插入语句
|
||||
placeholders = ', '.join(['%s'] * len(filtered_df.columns))
|
||||
# 使用反引号避免特殊列明
|
||||
columns = ', '.join([f"`{col}`" for col in filtered_df.columns])
|
||||
insert_sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
|
||||
|
||||
# 将 DataFrame 写入数据库
|
||||
for _, row in filtered_df.iterrows():
|
||||
cursor.execute(insert_sql, tuple(row))
|
||||
|
||||
connection.commit()
|
||||
print(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
|
||||
|
||||
except Exception as e:
|
||||
print("写入数据库时发生错误:", e)
|
||||
connection.rollback()
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
def clear_table_data(self):
|
||||
"""
|
||||
清空指定 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
|
||||
try:
|
||||
# 建立数据库连接
|
||||
connection = mysql.connector.connect(
|
||||
host=HS_DB_Config["host"],
|
||||
user=HS_DB_Config["user"],
|
||||
password=HS_DB_Config["password"],
|
||||
database=HS_DB_Config["database"]
|
||||
)
|
||||
if connection.is_connected():
|
||||
cursor = connection.cursor()
|
||||
|
||||
# 使用TRUNCATE清空表数据
|
||||
cursor.execute(f"TRUNCATE TABLE {table_name}")
|
||||
connection.commit()
|
||||
|
||||
print(f"成功清空表 {table_name} 中的所有数据")
|
||||
|
||||
except Error as e:
|
||||
print(f"清空表时发生错误: {e}")
|
||||
if connection and connection.is_connected():
|
||||
connection.rollback()
|
||||
finally:
|
||||
if connection and connection.is_connected():
|
||||
cursor.close()
|
||||
connection.close()
|
||||
print("数据库连接已关闭")
|
||||
|
||||
def main(self):
|
||||
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# step1: 获取数据
|
||||
self.load_all_data()
|
||||
|
||||
# step2:数据处理
|
||||
df = self.data_process()
|
||||
|
||||
|
||||
# # step3:数据库删除
|
||||
self.clear_table_data()
|
||||
#
|
||||
# # step4:数据写入BI
|
||||
self.write_to_bi(df)
|
||||
|
||||
common_module.send_task_status(task_start_time, "经销商新签服务单转BI")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = NewDealerServiceOrderToBI()
|
||||
start.main()
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,529 @@
|
||||
name,widgetName,label,type,items,app_id,entry_id
|
||||
_widget_1690785229260,_widget_1690785229260,怎么称呼您,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229261,_widget_1690785229261,您门店或公司名称,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693382214358,_widget_1693382214358,您的联系方式,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785326597,_widget_1690785326597,地址,address,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229266,_widget_1690785229266,备注,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229284,_widget_1690785229284,客户概况,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690787826014,_widget_1690787826014,门头照片(可上传多张),image,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229278,_widget_1690785229278,意向书来源,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1741837239117,_widget_1741837239117,业务类型,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022904,_widget_1693381022904,客户渠道,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1715146829031,_widget_1715146829031,轻连锁类型,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229280,_widget_1690785229280,小六,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1694154771486,_widget_1694154771486,技术专家,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229281,_widget_1690785229281,战区经理,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1718855270618,_widget_1718855270618,该养车门店是否已退出?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1718855270620,_widget_1718855270620,退出情况说明,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1718855270621,_widget_1718855270621,该养车门店是否有F6系统需求?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229282,_widget_1690785229282,意向阶段,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693551051341,_widget_1693551051341,客户门店数,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229283,_widget_1690785229283,意向版本,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022909,_widget_1693381022909,客户沟通记录,subform,"[{'name': '_widget_1693381022911', 'widgetName': '_widget_1693381022911', 'label': '跟进日期', 'type': 'datetime'}, {'name': '_widget_1693381022912', 'widgetName': '_widget_1693381022912', 'label': '沟通方式', 'type': 'combo'}, {'name': '_widget_1693381022914', 'widgetName': '_widget_1693381022914', 'label': '沟通概要', 'type': 'textarea'}]",66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022908,_widget_1693381022908,下次跟进日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1696902504775,_widget_1696902504775,理论下次跟进日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1694398435902,_widget_1694398435902,最近一次沟通日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022915,_widget_1693381022915,客户在用系统名称,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022916,_widget_1693381022916,预计成交金额(单位:元),number,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022917,_widget_1693381022917,预计成交日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1699321775702,_widget_1699321775702,实际成交日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022918,_widget_1693381022918,下单手机号,phone,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022919,_widget_1693381022919,放弃原因分类,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022921,_widget_1693381022921,价格原因,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022923,_widget_1693381022923,产品原因,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022925,_widget_1693381022925,门店原因,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022930,_widget_1693381022930,加盟外部连锁,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022927,_widget_1693381022927,内部业务影响(包含接车宝会员宝安装服务),radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1724313867483,_widget_1724313867483,输单原因分类,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1723603567435,_widget_1723603567435,竞品名称,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022929,_widget_1693381022929,输单/放弃说明,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626093,_widget_1708935626093,线索沟通情况,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709019633297,_widget_1709019633297,客户业务需求,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626085,_widget_1708935626085,客户手机号是否是微信号?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626087,_widget_1708935626087,企微是否已加好友?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626089,_widget_1708935626089,BOSS系统里是否有该客户信息,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709027488072,_widget_1709027488072,客户BOSS业务信息,checkboxgroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626095,_widget_1708935626095,联系人身份,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709100220536,_widget_1709100220536,门店业务类型,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626104,_widget_1708935626104,客户门店工位数,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626100,_widget_1708935626100,客户是否有需求,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626102,_widget_1708935626102,客户主要需求功能模块(可多选),checkboxgroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626107,_widget_1708935626107,客户原系统,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626091,_widget_1708935626091,客户预算,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626098,_widget_1708935626098,预计使用时间,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709186927667,_widget_1709186927667,门头照片等,image,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709100220453,_widget_1709100220453,SDR联系记录,subform,"[{'name': '_widget_1709100220457', 'widgetName': '_widget_1709100220457', 'label': '日期时间', 'type': 'datetime'}, {'name': '_widget_1709100220455', 'widgetName': '_widget_1709100220455', 'label': '联系情况', 'type': 'text'}]",66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626292,_widget_1708935626292,SDR判断客户是否需要进一步跟进,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1710292803370,_widget_1710292803370,SDR建议线索跟进时间,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1710037836605,_widget_1710037836605,线索放弃说明,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709543713740,_widget_1709543713740,SDR放弃意见,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725501916821,_widget_1725501916821,提交时间,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725507662927,_widget_1725507662927,提交人,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229279,_widget_1690785229279,城市,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1692070536228,_widget_1692070536228,区,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1697423018006,_widget_1697423018006,战区,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1694076921201,_widget_1694076921201,线上线下,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709868059118,_widget_1709868059118,线索跟进角色,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709781645383,_widget_1709781645383,客户跟进角色,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725875301461,_widget_1725875301461,技术支持提交人,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725933630175,_widget_1725933630175,是否有效线索,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229262,_widget_1690785229262,您的联系方式,phone,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1723431564839,_widget_1723431564839,线索状态,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_0201002000002,_widget_0201002000002,经销商名称,company,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401220,_widget_1732095401220,经销商简称,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401222,_widget_1732095401222,营业执照号,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401223,_widget_1732095401223,营业执照名称,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235945,_widget_1732153235945,详细地址,address,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401224,_widget_1732095401224,负责人姓名,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401225,_widget_1732095401225,负责人手机号,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401226,_widget_1732095401226,联系电话,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1742200662775,_widget_1742200662775,购买年限,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1742278002584,_widget_1742278002584,购买版本,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401227,_widget_1732095401227,经销商可购买的群数量,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000003,_widget_0201002000003,销售负责人,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235954,_widget_1732153235954,运营顾问,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235955,_widget_1732153235955,运营专家,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235956,_widget_1732153235956,区域经理,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1741165766484,_widget_1741165766484,业务,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732180937809,_widget_1732180937809,经销商ID,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732180937812,_widget_1732180937812,开通状态,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732180937811,_widget_1732180937811,开通时间,datetime,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1741160451740,_widget_1741160451740,系统到期时间,datetime,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1630862543415,_widget_1630862543415,客户状态,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1646826421878,_widget_1646826421878,客户邮箱,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1630862543637,_widget_1630862543637,所属行业,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732178180219,_widget_1732178180219,客户来源表单字段,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000004,_widget_0201002000004,协作人,usergroup,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1631071964934,_widget_1631071964934,客户详情,textarea,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1734062123070,_widget_1734062123070,门店名称,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123068,_widget_1734062123068,公司名称,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123071,_widget_1734062123071,门店编码,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123072,_widget_1734062123072,公司等级,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123073,_widget_1734062123073,门店类型,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123085,_widget_1734062123085,是否主店,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123067,_widget_1734062123067,公司id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123069,_widget_1734062123069,门店id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123169,_widget_1734062123169,经营模式,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123170,_widget_1734062123170,联系人,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123172,_widget_1734062123172,手机号码,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123179,_widget_1734062123179,是否主店,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123180,_widget_1734062123180,门店数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123066,_widget_1734062123066,日期,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123065,_widget_1734062123065,日期批次,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071375,_widget_1749000071375,日期(时间字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123192,_widget_1734062123192,是否加店,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123194,_widget_1734062123194,门店规模,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123196,_widget_1734062123196,经营范围,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123197,_widget_1734062123197,维修厂类型,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123199,_widget_1734062123199,工位数,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123201,_widget_1734062123201,门店阶段,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123203,_widget_1734062123203,门店分层,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1742890765211,_widget_1742890765211,门头照片,image,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123090,_widget_1734062123090,省,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123092,_widget_1734062123092,市,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123094,_widget_1734062123094,区,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123095,_widget_1734062123095,大区,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123097,_widget_1734062123097,小区,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123099,_widget_1734062123099,前置仓名称,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123102,_widget_1734062123102,区域经理,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123103,_widget_1734062123103,续约顾问,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123105,_widget_1734062123105,运营负责人,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123204,_widget_1734062123204,运营专家,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1748496855779,_widget_1748496855779,区域经理(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1748496855780,_widget_1748496855780,运营负责人(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1748496855778,_widget_1748496855778,续约顾问(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1751877712235,_widget_1751877712235,运营专家(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123075,_widget_1734062123075,ERP操作模式,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123076,_widget_1734062123076,公众号,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123077,_widget_1734062123077,小程序,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123078,_widget_1734062123078,微信商城,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123079,_widget_1734062123079,洗车摄像头,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123106,_widget_1734062123106,有效账户数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123175,_widget_1734062123175,安装服务,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123184,_widget_1734062123184,SaaS版本,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123074,_widget_1734062123074,客户状态,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123081,_widget_1734062123081,开户日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123082,_widget_1734062123082,应续约日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123083,_widget_1734062123083,使用天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123084,_widget_1734062123084,使用年数,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123176,_widget_1734062123176,上线日期,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123177,_widget_1734062123177,过期日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123178,_widget_1734062123178,实际续约日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071377,_widget_1749000071377,开户日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071382,_widget_1749000071382,应续约日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071384,_widget_1749000071384,上线日期(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071389,_widget_1749000071389,过期日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071391,_widget_1749000071391,实际续约日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123111,_widget_1734062123111,G状态,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123115,_widget_1734062123115,活跃状态,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123117,_widget_1734062123117,近30天业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123119,_widget_1734062123119,近7天业务单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123120,_widget_1734062123120,近7天业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123122,_widget_1734062123122,UV数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123167,_widget_1734062123167,G变化(月),text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123173,_widget_1734062123173,G月份,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123174,_widget_1734062123174,G转化率,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123182,_widget_1734062123182,G变化类型,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123183,_widget_1734062123183,G流失天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123185,_widget_1734062123185,M-1(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123186,_widget_1734062123186,M-2(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123187,_widget_1734062123187,M-3(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123188,_widget_1734062123188,M-4(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123189,_widget_1734062123189,M-5(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123190,_widget_1734062123190,M-6(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123191,_widget_1734062123191,G天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123202,_widget_1734062123202,本月G天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123116,_widget_1734062123116,近30天业务单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123155,_widget_1734062123155,近30天维修单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123156,_widget_1734062123156,近30天洗车单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123157,_widget_1734062123157,近30天维修开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123158,_widget_1734062123158,近30天洗车开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123159,_widget_1734062123159,近30天销售单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123160,_widget_1734062123160,近30天销售单开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123161,_widget_1734062123161,近30天采购单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123162,_widget_1734062123162,近30天采购开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123163,_widget_1734062123163,近30天卡业务单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123164,_widget_1734062123164,近30天卡业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123118,_widget_1734062123118,自然月业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123123,_widget_1734062123123,T_1开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123124,_widget_1734062123124,T_2开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123125,_widget_1734062123125,T_3开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123126,_widget_1734062123126,T_4开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123127,_widget_1734062123127,T_5开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123128,_widget_1734062123128,T_6开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123129,_widget_1734062123129,T_7开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123130,_widget_1734062123130,T_8开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123131,_widget_1734062123131,T_9开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123132,_widget_1734062123132,T_10开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123133,_widget_1734062123133,T_11开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123134,_widget_1734062123134,T_12开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123135,_widget_1734062123135,T_13开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123136,_widget_1734062123136,T_14开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123137,_widget_1734062123137,T_15开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123138,_widget_1734062123138,T_16开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123139,_widget_1734062123139,T_17开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123140,_widget_1734062123140,T_18开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123141,_widget_1734062123141,T_19开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123142,_widget_1734062123142,T_20开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123143,_widget_1734062123143,T_21开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123144,_widget_1734062123144,T_22开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123145,_widget_1734062123145,T_23开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123146,_widget_1734062123146,T_24开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123147,_widget_1734062123147,T_25开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123148,_widget_1734062123148,T_26开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123149,_widget_1734062123149,T_27开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123150,_widget_1734062123150,T_28开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123151,_widget_1734062123151,T_29开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123152,_widget_1734062123152,T_30开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123153,_widget_1734062123153,T_31开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123080,_widget_1734062123080,is_maintenance_service,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123086,_widget_1734062123086,license_code,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123087,_widget_1734062123087,license_name,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123088,_widget_1734062123088,org_crm_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123089,_widget_1734062123089,province_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123091,_widget_1734062123091,city_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123093,_widget_1734062123093,area_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123096,_widget_1734062123096,region_short_name,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123098,_widget_1734062123098,carzone_store_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123100,_widget_1734062123100,customer_carzone_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123101,_widget_1734062123101,salesmen,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123104,_widget_1734062123104,impl_principal,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123107,_widget_1734062123107,active_user_type,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123108,_widget_1734062123108,limit_user_count,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123109,_widget_1734062123109,limit_user_type,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123110,_widget_1734062123110,is_n,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123112,_widget_1734062123112,is_v,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123113,_widget_1734062123113,is_visited,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123114,_widget_1734062123114,is_active,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123121,_widget_1734062123121,pv_count,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123154,_widget_1734062123154,etl_time,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123165,_widget_1734062123165,gd_sales_bill_count_last_30_day,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123166,_widget_1734062123166,gd_sales_bill_day_count_last_30_day,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123168,_widget_1734062123168,saas_package,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123171,_widget_1734062123171,contact_number,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123181,_widget_1734062123181,recent_bill_warning_days,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123193,_widget_1734062123193,pt,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123195,_widget_1734062123195,qualification_type_fmt,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123198,_widget_1734062123198,area,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123200,_widget_1734062123200,header_type_fmt,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123205,_widget_1734062123205,tmall_maintain_service_status_desc,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1745908548852,_widget_1745908548852,江苏易捷门店归属公司,radiogroup,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1742795002375,_widget_1742795002375,公司ID,text,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002376,_widget_1742795002376,公众号名称,text,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002377,_widget_1742795002377,小程序模板类型,text,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002378,_widget_1742795002378,是否开通微信商城,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002379,_widget_1742795002379,上架商品数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002380,_widget_1742795002380,上架套餐卡数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002381,_widget_1742795002381,上架实体商品数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002382,_widget_1742795002382,上架项目数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002383,_widget_1742795002383,上架套餐数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002384,_widget_1742795002384,微信公众号粉丝数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002385,_widget_1742795002385,微信公众号绑定手机粉丝数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002386,_widget_1742795002386,是否开通微信小程序,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002387,_widget_1742795002387,微信小程序绑定用户数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002388,_widget_1742795002388,微信小程序绑定手机用户量,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002389,_widget_1742795002389,微信订单数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002390,_widget_1742795002390,微信支付订单量,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002391,_widget_1742795002391,线下订单数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742884710674,_widget_1742884710674,门店id,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884710675,_widget_1742884710675,提成类型_二级分类,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884710676,_widget_1742884710676,提成基数(本月),number,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884710677,_widget_1742884710677,提成基数(上月),number,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1748930441629,_widget_1748930441629,公司id,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1748931089356,_widget_1748931089356,门店编码,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1748931089357,_widget_1748931089357,门店名称,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884829007,_widget_1742884829007,门店id,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1742884829008,_widget_1742884829008,商品名称,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1742884829009,_widget_1742884829009,服务期结束时间,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1748930826642,_widget_1748930826642,公司id,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1748931208852,_widget_1748931208852,门店编码,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1748931208851,_widget_1748931208851,门店名称,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1743065201885,_widget_1743065201885,公司id,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201886,_widget_1743065201886,是否启动短信功能,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201887,_widget_1743065201887,是否购买短信包,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201888,_widget_1743065201888,累计购买总数,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201889,_widget_1743065201889,累计发送成功总人数,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201890,_widget_1743065201890,剩余短信条数,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201891,_widget_1743065201891,第一次短信购买时间,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201892,_widget_1743065201892,最近一次短信购买时间,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201893,_widget_1743065201893,实付总金额,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201894,_widget_1743065201894,短信剩余量是否小于20%,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1748241895830,_widget_1748241895830,门店名称,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895831,_widget_1748241895831,联系人,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895839,_widget_1748241895839,开户时间,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895842,_widget_1748241895842,门店编码,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895832,_widget_1748241895832,联系方式,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895850,_widget_1748241895850,系统版本,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895844,_widget_1748241895844,公司名称,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808679,_widget_1748246808679,运营顾问,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808682,_widget_1748246808682,区域经理,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895846,_widget_1748241895846,公司等级,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808681,_widget_1748246808681,运营专家,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895853,_widget_1748241895853,操作模式E.L/E.S,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895829,_widget_1748241895829,活跃健康状态变化,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895833,_widget_1748241895833,初始日,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895834,_widget_1748241895834,推进日,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176640,_widget_1748512176640,异常跟进情况描述,textarea,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176641,_widget_1748512176641,异常变化原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176643,_widget_1748512176643,正常使用,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176645,_widget_1748512176645,门店原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176647,_widget_1748512176647,服务原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176649,_widget_1748512176649,产品原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176651,_widget_1748512176651,未正式切换,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176655,_widget_1748512176655,跟进状态,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808678,_widget_1748246808678,当前跟进人,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176654,_widget_1748512176654,跟进时间,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1751273412737,_widget_1751273412737,是否跟进完成,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808680,_widget_1748246808680,区域客服,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895847,_widget_1748241895847,大区,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895848,_widget_1748241895848,省,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895855,_widget_1748241895855,城市,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895849,_widget_1748241895849,门店类型,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895851,_widget_1748241895851,saas客户类型,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895852,_widget_1748241895852,门店阶段,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748247754304,_widget_1748247754304,关联数据,lookup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1751250294777,_widget_1751250294777,姓名1,text,,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a
|
||||
_widget_1751505196330,_widget_1751505196330,图片,image,,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a
|
||||
_widget_1751507507755,_widget_1751507507755,定位,location,,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a
|
||||
_widget_1739951204545,_widget_1739951204545,表单类型,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804406,_widget_1739252804406,日期,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739258942667,_widget_1739258942667,账号,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804419,_widget_1739252804419,日分区,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804397,_widget_1739252804397,产品名称,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804407,_widget_1739252804407,联系手机号,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804409,_widget_1739252804409,使用时长,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804396,_widget_1739252804396,开户日,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804408,_widget_1739252804408,到期日,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804410,_widget_1739252804410,续约日,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804400,_widget_1739252804400,客户状态,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804413,_widget_1739252804413,近一周开单量,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804414,_widget_1739252804414,近一周是否活跃,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804415,_widget_1739252804415,G状态:近30天开单大于等于10天,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804416,_widget_1739252804416,当月开单天数,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804417,_widget_1739252804417,近30天开单天数,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804418,_widget_1739252804418,当月G天数,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740036367181,_widget_1740036367181,派发日期,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740043340255,_widget_1740043340255,跟进人,user,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143304,_widget_1741252143304,是否联系上·新签,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143306,_widget_1741252143306,是否联系上·异常,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143308,_widget_1741252143308,是否联系上·续约商机,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143310,_widget_1741252143310,是否联系上·过期召回,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741256466947,_widget_1741256466947,未接通原因备注,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384110,_widget_1740721384110,省市区,address,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741312871468,_widget_1741312871468,省市区·续约,address,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384111,_widget_1740721384111,门店名称,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741312871469,_widget_1741312871469,门店名称·续约,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384112,_widget_1740721384112,负责人姓名,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741312871470,_widget_1741312871470,负责人姓名·续约,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384122,_widget_1740721384122,回访人·新签,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384117,_widget_1740721384117,未开单原因·新签,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384125,_widget_1740721384125,是否愿意继续使用·新签,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384127,_widget_1740721384127,回访人·异常,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384128,_widget_1740721384128,未开单原因·异常,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384129,_widget_1740721384129,是否愿意继续使用·异常,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384131,_widget_1740721384131,回访人·续约商机,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384132,_widget_1740721384132,是否有转化SaaS意愿·续约商机,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384133,_widget_1740721384133,系统使用情况·续约商机,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749088869175,_widget_1749088869175,SaaS转化结果·续约商机,radiogroup,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749088869177,_widget_1749088869177,转化SaaS订单号·续约商机,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749088869190,_widget_1749088869190,其他转化结果·续约商机,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384135,_widget_1740721384135,回访人·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384136,_widget_1740721384136,未续约单原因·过期召回,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384137,_widget_1740721384137,是否有续约意愿·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854370,_widget_1749090854370,沟通跟进结果·过期召回,radiogroup,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854372,_widget_1749090854372,转化SaaS订单号·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854373,_widget_1749090854373,接车宝续约订单号·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854374,_widget_1749090854374,其他召回情况说明·过期召回,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1751356539629,_widget_1751356539629,完成日期时间,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1751271771674,_widget_1751271771674,是否完成,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1751356033346,_widget_1751356033346,流水号,sn,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740042824214,_widget_1740042824214,客服人员,user,,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a
|
||||
_widget_1740117343937,_widget_1740117343937,开关,combo,,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a
|
||||
_widget_1740042824216,_widget_1740042824216,下次开始位置,text,,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a
|
||||
_widget_1740723898388,_widget_1740723898388,日期,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898389,_widget_1740723898389,产品名称,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898390,_widget_1740723898390,账号,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898391,_widget_1740723898391,联系手机号,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898392,_widget_1740723898392,开户日,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898393,_widget_1740723898393,使用时长,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898394,_widget_1740723898394,续约日,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898395,_widget_1740723898395,到期日,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898396,_widget_1740723898396,客户状态,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898397,_widget_1740723898397,近一周开单量,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898398,_widget_1740723898398,近一周是否活跃,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898399,_widget_1740723898399,G状态:近30天开单大于等于10天,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898400,_widget_1740723898400,当月开单天数,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898401,_widget_1740723898401,近30天开单天数,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898402,_widget_1740723898402,当月G天数,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898403,_widget_1740723898403,日分区,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898404,_widget_1740723898404,表单类型,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898405,_widget_1740723898405,派发日期,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000002,_widget_0201002000002,门店名称,company,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1750126318263,_widget_1750126318263,门店名称(后台传值),text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108119,_widget_1746675108119,原系统名称,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749204198412,_widget_1749204198412,原系统情况描述,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1630862543637,_widget_1630862543637,门店类型,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108151,_widget_1746675108151,门店设备,combocheck,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108121,_widget_1746675108121,门店业务,combocheck,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108115,_widget_1746675108115,工位数,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747321321284,_widget_1747321321284,员工数,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108123,_widget_1746675108123,系统操作人员,combocheck,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097782383,_widget_1737097782383,门店环境,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1630862543415,_widget_1630862543415,BD状态,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933309,_widget_1747123933309,客户BD日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1751366502797,_widget_1751366502797,意向程度,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747661411161,_widget_1747661411161,Test开始日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747661411178,_widget_1747661411178,Test天数,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747664949166,_widget_1747664949166,Test账号状态,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000003,_widget_0201002000003,BD负责人,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000004,_widget_0201002000004,BD协作人,usergroup,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747133970117,_widget_1747133970117,BD阻塞原因,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747669642443,_widget_1747669642443,BD阻塞原因分类,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747133970121,_widget_1747133970121,BD阻塞原因详细描述,textarea,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749290572780,_widget_1749290572780,签约&上线负责人,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933310,_widget_1747123933310,客户签约日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933311,_widget_1747123933311,客户付款日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749632087678,_widget_1749632087678,付款金额(泰铢),number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749632087641,_widget_1749632087641,付款截图,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749632087639,_widget_1749632087639,上传发票附件,upload,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1740460160201,_widget_1740460160201,上线状态,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933312,_widget_1747123933312,上线日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747133970122,_widget_1747133970122,上线失败原因,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1631071964934,_widget_1631071964934,上线失败原因描述,textarea,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749108058561,_widget_1749108058561,门店系统使用情况说明,textarea,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123507416,_widget_1747123507416,开户门店ID,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013289,_widget_1737092013289,公司名称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013291,_widget_1737092013291,主店简称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013292,_widget_1737092013292,营业执照号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013293,_widget_1737092013293,营业执照名称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013300,_widget_1737092013300,门店logo,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013301,_widget_1737092013301,pc首页左上角logo,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013302,_widget_1737092013302,pc首页左上角logo缩略图,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013321,_widget_1737092013321,门头照片,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097231480,_widget_1737097231480,府,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097231482,_widget_1737097231482,县,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013299,_widget_1737092013299,地址(省市区),text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097782393,_widget_1737097782393,详情地址,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013314,_widget_1737092013314,营业开始时间,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013313,_widget_1737092013313,营业结束时间,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013312,_widget_1737092013312,经度,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013311,_widget_1737092013311,纬度,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013310,_widget_1737092013310,负责人名字,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013308,_widget_1737092013308,负责人手机号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013309,_widget_1737092013309,服务接待固话,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013315,_widget_1737092013315,服务接待名称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013316,_widget_1737092013316,服务接待手机号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013320,_widget_1737092013320,账号数上限,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013318,_widget_1737092013318,税号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013317,_widget_1737092013317,分支编号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013319,_widget_1737092013319,嘉实多内部门店编码,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013339,_widget_1737092013339,运营顾问(上线负责人),user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013340,_widget_1737092013340,运营专家,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013341,_widget_1737092013341,区域经理,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1750125550901,_widget_1750125550901,状态,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1742174728275,_widget_1742174728275,指标归属日期,datetime,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963874,_widget_1742091963874,公司ID,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963875,_widget_1742091963875,公司名称,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963876,_widget_1742091963876,门店ID,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963877,_widget_1742091963877,门店名称,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963878,_widget_1742091963878,门店简称,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963879,_widget_1742091963879,门店创建时间,datetime,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963880,_widget_1742091963880,指标类型,combo,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963881,_widget_1742091963881,指标子类型,combo,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963882,_widget_1742091963882,指标值,number,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_0201002000002,_widget_0201002000002,客户名称,company,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1630862543415,_widget_1630862543415,客户状态,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1630862543637,_widget_1630862543637,所属行业,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1646826421878,_widget_1646826421878,客户邮箱,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1631071964919,_widget_1631071964919,客户地址,address,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1631071964934,_widget_1631071964934,客户详情,textarea,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000003,_widget_0201002000003,销售负责人,user,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000004,_widget_0201002000004,协作人,usergroup,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,530 @@
|
||||
name,widgetName,label,type,app_id,entry_id,items
|
||||
_widget_1690785229260,_widget_1690785229260,怎么称呼您,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229261,_widget_1690785229261,您门店或公司名称,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693382214358,_widget_1693382214358,您的联系方式,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785326597,_widget_1690785326597,地址,address,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229266,_widget_1690785229266,备注,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229284,_widget_1690785229284,客户概况,textarea,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690787826014,_widget_1690787826014,门头照片(可上传多张),image,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229278,_widget_1690785229278,意向书来源,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1741837239117,_widget_1741837239117,业务类型,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022904,_widget_1693381022904,客户渠道,combo,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1715146829031,_widget_1715146829031,轻连锁类型,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229280,_widget_1690785229280,小六,user,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1694154771486,_widget_1694154771486,技术专家,user,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229281,_widget_1690785229281,战区经理,user,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1718855270618,_widget_1718855270618,该养车门店是否已退出?,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1718855270620,_widget_1718855270620,退出情况说明,textarea,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1718855270621,_widget_1718855270621,该养车门店是否有F6系统需求?,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229282,_widget_1690785229282,意向阶段,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693551051341,_widget_1693551051341,客户门店数,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229283,_widget_1690785229283,意向版本,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022909,_widget_1693381022909,客户沟通记录,subform,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,"[{'name': '_widget_1693381022911', 'widgetName': '_widget_1693381022911', 'label': '跟进日期', 'type': 'datetime'}, {'name': '_widget_1693381022912', 'widgetName': '_widget_1693381022912', 'label': '沟通方式', 'type': 'combo'}, {'name': '_widget_1693381022914', 'widgetName': '_widget_1693381022914', 'label': '沟通概要', 'type': 'textarea'}]"
|
||||
_widget_1693381022908,_widget_1693381022908,下次跟进日期,datetime,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1696902504775,_widget_1696902504775,理论下次跟进日期,datetime,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1694398435902,_widget_1694398435902,最近一次沟通日期,datetime,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022915,_widget_1693381022915,客户在用系统名称,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022916,_widget_1693381022916,预计成交金额(单位:元),number,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022917,_widget_1693381022917,预计成交日期,datetime,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1699321775702,_widget_1699321775702,实际成交日期,datetime,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022918,_widget_1693381022918,下单手机号,phone,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022919,_widget_1693381022919,放弃原因分类,combo,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022921,_widget_1693381022921,价格原因,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022923,_widget_1693381022923,产品原因,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022925,_widget_1693381022925,门店原因,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022930,_widget_1693381022930,加盟外部连锁,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022927,_widget_1693381022927,内部业务影响(包含接车宝会员宝安装服务),radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1724313867483,_widget_1724313867483,输单原因分类,combo,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1723603567435,_widget_1723603567435,竞品名称,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1693381022929,_widget_1693381022929,输单/放弃说明,textarea,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626093,_widget_1708935626093,线索沟通情况,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709019633297,_widget_1709019633297,客户业务需求,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626085,_widget_1708935626085,客户手机号是否是微信号?,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626087,_widget_1708935626087,企微是否已加好友?,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626089,_widget_1708935626089,BOSS系统里是否有该客户信息,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709027488072,_widget_1709027488072,客户BOSS业务信息,checkboxgroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626095,_widget_1708935626095,联系人身份,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709100220536,_widget_1709100220536,门店业务类型,combo,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626104,_widget_1708935626104,客户门店工位数,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626100,_widget_1708935626100,客户是否有需求,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626102,_widget_1708935626102,客户主要需求功能模块(可多选),checkboxgroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626107,_widget_1708935626107,客户原系统,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626091,_widget_1708935626091,客户预算,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1708935626098,_widget_1708935626098,预计使用时间,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709186927667,_widget_1709186927667,门头照片等,image,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709100220453,_widget_1709100220453,SDR联系记录,subform,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,"[{'name': '_widget_1709100220457', 'widgetName': '_widget_1709100220457', 'label': '日期时间', 'type': 'datetime'}, {'name': '_widget_1709100220455', 'widgetName': '_widget_1709100220455', 'label': '联系情况', 'type': 'text'}]"
|
||||
_widget_1708935626292,_widget_1708935626292,SDR判断客户是否需要进一步跟进,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1710292803370,_widget_1710292803370,SDR建议线索跟进时间,combo,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1710037836605,_widget_1710037836605,线索放弃说明,textarea,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709543713740,_widget_1709543713740,SDR放弃意见,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1725501916821,_widget_1725501916821,提交时间,datetime,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1725507662927,_widget_1725507662927,提交人,user,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229279,_widget_1690785229279,城市,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1692070536228,_widget_1692070536228,区,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1697423018006,_widget_1697423018006,战区,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1694076921201,_widget_1694076921201,线上线下,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709868059118,_widget_1709868059118,线索跟进角色,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1709781645383,_widget_1709781645383,客户跟进角色,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1725875301461,_widget_1725875301461,技术支持提交人,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1725933630175,_widget_1725933630175,是否有效线索,text,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1690785229262,_widget_1690785229262,您的联系方式,phone,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_1723431564839,_widget_1723431564839,线索状态,radiogroup,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd,
|
||||
_widget_0201002000002,_widget_0201002000002,经销商名称,company,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401220,_widget_1732095401220,经销商简称,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401222,_widget_1732095401222,营业执照号,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401223,_widget_1732095401223,营业执照名称,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732153235945,_widget_1732153235945,详细地址,address,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401224,_widget_1732095401224,负责人姓名,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401225,_widget_1732095401225,负责人手机号,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401226,_widget_1732095401226,联系电话,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1742200662775,_widget_1742200662775,购买年限,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1742278002584,_widget_1742278002584,购买版本,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732095401227,_widget_1732095401227,经销商可购买的群数量,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_0201002000003,_widget_0201002000003,销售负责人,user,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732153235954,_widget_1732153235954,运营顾问,user,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732153235955,_widget_1732153235955,运营专家,user,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732153235956,_widget_1732153235956,区域经理,user,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1741165766484,_widget_1741165766484,业务,user,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732180937809,_widget_1732180937809,经销商ID,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732180937812,_widget_1732180937812,开通状态,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732180937811,_widget_1732180937811,开通时间,datetime,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1741160451740,_widget_1741160451740,系统到期时间,datetime,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1630862543415,_widget_1630862543415,客户状态,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1646826421878,_widget_1646826421878,客户邮箱,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1630862543637,_widget_1630862543637,所属行业,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1732178180219,_widget_1732178180219,客户来源表单字段,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_0201002000004,_widget_0201002000004,协作人,usergroup,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1631071964934,_widget_1631071964934,客户详情,textarea,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,673d8427549d00c3d753c530,020100200000000000000001,
|
||||
_widget_1734062123070,_widget_1734062123070,门店名称,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123068,_widget_1734062123068,公司名称,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123071,_widget_1734062123071,门店编码,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123072,_widget_1734062123072,公司等级,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123073,_widget_1734062123073,门店类型,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123085,_widget_1734062123085,是否主店,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123067,_widget_1734062123067,公司id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123069,_widget_1734062123069,门店id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123169,_widget_1734062123169,经营模式,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123170,_widget_1734062123170,联系人,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123172,_widget_1734062123172,手机号码,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123179,_widget_1734062123179,是否主店,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123180,_widget_1734062123180,门店数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123066,_widget_1734062123066,日期,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123065,_widget_1734062123065,日期批次,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1749000071375,_widget_1749000071375,日期(时间字段),datetime,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123192,_widget_1734062123192,是否加店,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123194,_widget_1734062123194,门店规模,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123196,_widget_1734062123196,经营范围,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123197,_widget_1734062123197,维修厂类型,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123199,_widget_1734062123199,工位数,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123201,_widget_1734062123201,门店阶段,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123203,_widget_1734062123203,门店分层,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1742890765211,_widget_1742890765211,门头照片,image,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123090,_widget_1734062123090,省,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123092,_widget_1734062123092,市,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123094,_widget_1734062123094,区,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123095,_widget_1734062123095,大区,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123097,_widget_1734062123097,小区,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123099,_widget_1734062123099,前置仓名称,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123102,_widget_1734062123102,区域经理,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123103,_widget_1734062123103,续约顾问,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123105,_widget_1734062123105,运营负责人,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123204,_widget_1734062123204,运营专家,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1748496855779,_widget_1748496855779,区域经理(成员字段),user,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1748496855780,_widget_1748496855780,运营负责人(成员字段),user,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1748496855778,_widget_1748496855778,续约顾问(成员字段),user,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123075,_widget_1734062123075,ERP操作模式,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123076,_widget_1734062123076,公众号,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123077,_widget_1734062123077,小程序,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123078,_widget_1734062123078,微信商城,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123079,_widget_1734062123079,洗车摄像头,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123106,_widget_1734062123106,有效账户数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123175,_widget_1734062123175,安装服务,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123184,_widget_1734062123184,SaaS版本,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123074,_widget_1734062123074,客户状态,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123081,_widget_1734062123081,开户日,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123082,_widget_1734062123082,应续约日,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123083,_widget_1734062123083,使用天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123084,_widget_1734062123084,使用年数,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123176,_widget_1734062123176,上线日期,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123177,_widget_1734062123177,过期日,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123178,_widget_1734062123178,实际续约日,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1749000071377,_widget_1749000071377,开户日(日期字段),datetime,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1749000071382,_widget_1749000071382,应续约日(日期字段),datetime,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1749000071384,_widget_1749000071384,上线日期(日期字段),datetime,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1749000071389,_widget_1749000071389,过期日(日期字段),datetime,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1749000071391,_widget_1749000071391,实际续约日(日期字段),datetime,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123111,_widget_1734062123111,G状态,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123115,_widget_1734062123115,活跃状态,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123117,_widget_1734062123117,近30天业务天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123119,_widget_1734062123119,近7天业务单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123120,_widget_1734062123120,近7天业务天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123122,_widget_1734062123122,UV数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123167,_widget_1734062123167,G变化(月),text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123173,_widget_1734062123173,G月份,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123174,_widget_1734062123174,G转化率,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123182,_widget_1734062123182,G变化类型,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123183,_widget_1734062123183,G流失天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123185,_widget_1734062123185,M-1(G),number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123186,_widget_1734062123186,M-2(G),number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123187,_widget_1734062123187,M-3(G),number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123188,_widget_1734062123188,M-4(G),number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123189,_widget_1734062123189,M-5(G),number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123190,_widget_1734062123190,M-6(G),number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123191,_widget_1734062123191,G天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123202,_widget_1734062123202,本月G天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123116,_widget_1734062123116,近30天业务单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123155,_widget_1734062123155,近30天维修单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123156,_widget_1734062123156,近30天洗车单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123157,_widget_1734062123157,近30天维修开单天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123158,_widget_1734062123158,近30天洗车开单天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123159,_widget_1734062123159,近30天销售单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123160,_widget_1734062123160,近30天销售单开单天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123161,_widget_1734062123161,近30天采购单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123162,_widget_1734062123162,近30天采购开单天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123163,_widget_1734062123163,近30天卡业务单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123164,_widget_1734062123164,近30天卡业务天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123118,_widget_1734062123118,自然月业务天数,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123123,_widget_1734062123123,T_1开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123124,_widget_1734062123124,T_2开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123125,_widget_1734062123125,T_3开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123126,_widget_1734062123126,T_4开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123127,_widget_1734062123127,T_5开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123128,_widget_1734062123128,T_6开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123129,_widget_1734062123129,T_7开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123130,_widget_1734062123130,T_8开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123131,_widget_1734062123131,T_9开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123132,_widget_1734062123132,T_10开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123133,_widget_1734062123133,T_11开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123134,_widget_1734062123134,T_12开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123135,_widget_1734062123135,T_13开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123136,_widget_1734062123136,T_14开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123137,_widget_1734062123137,T_15开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123138,_widget_1734062123138,T_16开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123139,_widget_1734062123139,T_17开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123140,_widget_1734062123140,T_18开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123141,_widget_1734062123141,T_19开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123142,_widget_1734062123142,T_20开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123143,_widget_1734062123143,T_21开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123144,_widget_1734062123144,T_22开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123145,_widget_1734062123145,T_23开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123146,_widget_1734062123146,T_24开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123147,_widget_1734062123147,T_25开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123148,_widget_1734062123148,T_26开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123149,_widget_1734062123149,T_27开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123150,_widget_1734062123150,T_28开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123151,_widget_1734062123151,T_29开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123152,_widget_1734062123152,T_30开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123153,_widget_1734062123153,T_31开单量,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123080,_widget_1734062123080,is_maintenance_service,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123086,_widget_1734062123086,license_code,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123087,_widget_1734062123087,license_name,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123088,_widget_1734062123088,org_crm_id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123089,_widget_1734062123089,province_id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123091,_widget_1734062123091,city_id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123093,_widget_1734062123093,area_id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123096,_widget_1734062123096,region_short_name,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123098,_widget_1734062123098,carzone_store_id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123100,_widget_1734062123100,customer_carzone_id,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123101,_widget_1734062123101,salesmen,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123104,_widget_1734062123104,impl_principal,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123107,_widget_1734062123107,active_user_type,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123108,_widget_1734062123108,limit_user_count,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123109,_widget_1734062123109,limit_user_type,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123110,_widget_1734062123110,is_n,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123112,_widget_1734062123112,is_v,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123113,_widget_1734062123113,is_visited,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123114,_widget_1734062123114,is_active,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123121,_widget_1734062123121,pv_count,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123154,_widget_1734062123154,etl_time,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123165,_widget_1734062123165,gd_sales_bill_count_last_30_day,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123166,_widget_1734062123166,gd_sales_bill_day_count_last_30_day,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123168,_widget_1734062123168,saas_package,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123171,_widget_1734062123171,contact_number,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123181,_widget_1734062123181,recent_bill_warning_days,number,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123193,_widget_1734062123193,pt,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123195,_widget_1734062123195,qualification_type_fmt,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123198,_widget_1734062123198,area,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123200,_widget_1734062123200,header_type_fmt,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1734062123205,_widget_1734062123205,tmall_maintain_service_status_desc,text,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1745908548852,_widget_1745908548852,江苏易捷门店归属公司,radiogroup,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4,
|
||||
_widget_1742795002375,_widget_1742795002375,公司ID,text,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002376,_widget_1742795002376,公众号名称,text,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002377,_widget_1742795002377,小程序模板类型,text,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002378,_widget_1742795002378,是否开通微信商城,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002379,_widget_1742795002379,上架商品数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002380,_widget_1742795002380,上架套餐卡数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002381,_widget_1742795002381,上架实体商品数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002382,_widget_1742795002382,上架项目数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002383,_widget_1742795002383,上架套餐数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002384,_widget_1742795002384,微信公众号粉丝数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002385,_widget_1742795002385,微信公众号绑定手机粉丝数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002386,_widget_1742795002386,是否开通微信小程序,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002387,_widget_1742795002387,微信小程序绑定用户数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002388,_widget_1742795002388,微信小程序绑定手机用户量,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002389,_widget_1742795002389,微信订单数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002390,_widget_1742795002390,微信支付订单量,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742795002391,_widget_1742795002391,线下订单数,number,675b900991ad2491c69389ca,67e0f0fae622896749ba5087,
|
||||
_widget_1742884710674,_widget_1742884710674,门店id,text,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1742884710675,_widget_1742884710675,提成类型_二级分类,text,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1742884710676,_widget_1742884710676,提成基数(本月),number,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1742884710677,_widget_1742884710677,提成基数(上月),number,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1748930441629,_widget_1748930441629,公司id,text,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1748931089356,_widget_1748931089356,门店编码,text,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1748931089357,_widget_1748931089357,门店名称,text,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589,
|
||||
_widget_1742884829007,_widget_1742884829007,门店id,text,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b,
|
||||
_widget_1742884829008,_widget_1742884829008,商品名称,text,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b,
|
||||
_widget_1742884829009,_widget_1742884829009,服务期结束时间,text,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b,
|
||||
_widget_1748930826642,_widget_1748930826642,公司id,text,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b,
|
||||
_widget_1748931208852,_widget_1748931208852,门店编码,text,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b,
|
||||
_widget_1748931208851,_widget_1748931208851,门店名称,text,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b,
|
||||
_widget_1743065201885,_widget_1743065201885,公司id,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201886,_widget_1743065201886,是否启动短信功能,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201887,_widget_1743065201887,是否购买短信包,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201888,_widget_1743065201888,累计购买总数,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201889,_widget_1743065201889,累计发送成功总人数,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201890,_widget_1743065201890,剩余短信条数,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201891,_widget_1743065201891,第一次短信购买时间,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201892,_widget_1743065201892,最近一次短信购买时间,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201893,_widget_1743065201893,实付总金额,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1743065201894,_widget_1743065201894,短信剩余量是否小于20%,text,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974,
|
||||
_widget_1748241895830,_widget_1748241895830,门店名称,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895831,_widget_1748241895831,联系人,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895839,_widget_1748241895839,开户时间,datetime,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895842,_widget_1748241895842,门店编码,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895832,_widget_1748241895832,联系方式,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895850,_widget_1748241895850,系统版本,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895844,_widget_1748241895844,公司名称,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748246808679,_widget_1748246808679,运营顾问,user,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748246808682,_widget_1748246808682,区域经理,user,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895846,_widget_1748241895846,公司等级,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748246808681,_widget_1748246808681,运营专家,user,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895853,_widget_1748241895853,操作模式E.L/E.S,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895829,_widget_1748241895829,活跃健康状态变化,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895833,_widget_1748241895833,初始日,datetime,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895834,_widget_1748241895834,推进日,datetime,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176640,_widget_1748512176640,异常跟进情况描述,textarea,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176641,_widget_1748512176641,异常变化原因,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176643,_widget_1748512176643,正常使用,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176645,_widget_1748512176645,门店原因,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176647,_widget_1748512176647,服务原因,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176649,_widget_1748512176649,产品原因,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176651,_widget_1748512176651,未正式切换,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176655,_widget_1748512176655,跟进状态,radiogroup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748246808678,_widget_1748246808678,当前跟进人,user,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748512176654,_widget_1748512176654,跟进时间,datetime,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1751273412737,_widget_1751273412737,是否跟进完成,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748246808680,_widget_1748246808680,区域客服,user,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895847,_widget_1748241895847,大区,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895848,_widget_1748241895848,省,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895855,_widget_1748241895855,城市,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895849,_widget_1748241895849,门店类型,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895851,_widget_1748241895851,saas客户类型,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748241895852,_widget_1748241895852,门店阶段,text,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1748247754304,_widget_1748247754304,关联数据,lookup,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc,
|
||||
_widget_1751250294777,_widget_1751250294777,姓名,text,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a,
|
||||
_widget_1751250294778,_widget_1751250294778,年纪,number,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a,
|
||||
_widget_1751505196330,_widget_1751505196330,图片,image,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a,
|
||||
_widget_1751507507755,_widget_1751507507755,定位,location,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a,
|
||||
_widget_1751512443179,_widget_1751512443179,单行文本,text,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a,
|
||||
_widget_1739951204545,_widget_1739951204545,表单类型,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804406,_widget_1739252804406,日期,datetime,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739258942667,_widget_1739258942667,账号,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804419,_widget_1739252804419,日分区,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804397,_widget_1739252804397,产品名称,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804407,_widget_1739252804407,联系手机号,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804409,_widget_1739252804409,使用时长,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804396,_widget_1739252804396,开户日,datetime,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804408,_widget_1739252804408,到期日,datetime,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804410,_widget_1739252804410,续约日,datetime,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804400,_widget_1739252804400,客户状态,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804413,_widget_1739252804413,近一周开单量,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804414,_widget_1739252804414,近一周是否活跃,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804415,_widget_1739252804415,G状态:近30天开单大于等于10天,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804416,_widget_1739252804416,当月开单天数,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804417,_widget_1739252804417,近30天开单天数,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1739252804418,_widget_1739252804418,当月G天数,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740036367181,_widget_1740036367181,派发日期,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740043340255,_widget_1740043340255,跟进人,user,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741252143304,_widget_1741252143304,是否联系上·新签,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741252143306,_widget_1741252143306,是否联系上·异常,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741252143308,_widget_1741252143308,是否联系上·续约商机,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741252143310,_widget_1741252143310,是否联系上·过期召回,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741256466947,_widget_1741256466947,未接通原因备注,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384110,_widget_1740721384110,省市区,address,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741312871468,_widget_1741312871468,省市区·续约,address,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384111,_widget_1740721384111,门店名称,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741312871469,_widget_1741312871469,门店名称·续约,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384112,_widget_1740721384112,负责人姓名,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1741312871470,_widget_1741312871470,负责人姓名·续约,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384122,_widget_1740721384122,回访人·新签,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384117,_widget_1740721384117,未开单原因·新签,textarea,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384125,_widget_1740721384125,是否愿意继续使用·新签,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384127,_widget_1740721384127,回访人·异常,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384128,_widget_1740721384128,未开单原因·异常,textarea,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384129,_widget_1740721384129,是否愿意继续使用·异常,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384131,_widget_1740721384131,回访人·续约商机,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384132,_widget_1740721384132,是否有转化SaaS意愿·续约商机,combo,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384133,_widget_1740721384133,系统使用情况·续约商机,textarea,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749088869175,_widget_1749088869175,SaaS转化结果·续约商机,radiogroup,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749088869177,_widget_1749088869177,转化SaaS订单号·续约商机,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749088869190,_widget_1749088869190,其他转化结果·续约商机,textarea,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384135,_widget_1740721384135,回访人·过期召回,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384136,_widget_1740721384136,未续约单原因·过期召回,textarea,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740721384137,_widget_1740721384137,是否有续约意愿·过期召回,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749090854370,_widget_1749090854370,沟通跟进结果·过期召回,radiogroup,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749090854372,_widget_1749090854372,转化SaaS订单号·过期召回,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749090854373,_widget_1749090854373,接车宝续约订单号·过期召回,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1749090854374,_widget_1749090854374,其他召回情况说明·过期召回,textarea,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1751356539629,_widget_1751356539629,完成日期时间,datetime,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1751271771674,_widget_1751271771674,是否完成,text,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1751356033346,_widget_1751356033346,流水号,sn,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1,
|
||||
_widget_1740042824214,_widget_1740042824214,客服人员,user,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a,
|
||||
_widget_1740117343937,_widget_1740117343937,开关,combo,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a,
|
||||
_widget_1740042824216,_widget_1740042824216,下次开始位置,text,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a,
|
||||
_widget_1740723898388,_widget_1740723898388,日期,datetime,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898389,_widget_1740723898389,产品名称,text,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898390,_widget_1740723898390,账号,text,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898391,_widget_1740723898391,联系手机号,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898392,_widget_1740723898392,开户日,datetime,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898393,_widget_1740723898393,使用时长,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898394,_widget_1740723898394,续约日,text,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898395,_widget_1740723898395,到期日,datetime,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898396,_widget_1740723898396,客户状态,text,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898397,_widget_1740723898397,近一周开单量,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898398,_widget_1740723898398,近一周是否活跃,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898399,_widget_1740723898399,G状态:近30天开单大于等于10天,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898400,_widget_1740723898400,当月开单天数,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898401,_widget_1740723898401,近30天开单天数,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898402,_widget_1740723898402,当月G天数,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898403,_widget_1740723898403,日分区,number,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898404,_widget_1740723898404,表单类型,text,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_1740723898405,_widget_1740723898405,派发日期,datetime,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110,
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_0201002000002,_widget_0201002000002,门店名称,company,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1750126318263,_widget_1750126318263,门店名称(后台传值),text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1746675108119,_widget_1746675108119,原系统名称,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1749204198412,_widget_1749204198412,原系统情况描述,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1630862543637,_widget_1630862543637,门店类型,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1746675108151,_widget_1746675108151,门店设备,combocheck,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1746675108121,_widget_1746675108121,门店业务,combocheck,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1746675108115,_widget_1746675108115,工位数,number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747321321284,_widget_1747321321284,员工数,number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1746675108123,_widget_1746675108123,系统操作人员,combocheck,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737097782383,_widget_1737097782383,门店环境,image,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1630862543415,_widget_1630862543415,BD状态,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747123933309,_widget_1747123933309,客户BD日期,datetime,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1751366502797,_widget_1751366502797,意向程度,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747661411161,_widget_1747661411161,Test开始日期,datetime,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747661411178,_widget_1747661411178,Test天数,number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747664949166,_widget_1747664949166,Test账号状态,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_0201002000003,_widget_0201002000003,BD负责人,user,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_0201002000004,_widget_0201002000004,BD协作人,usergroup,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747133970117,_widget_1747133970117,BD阻塞原因,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747669642443,_widget_1747669642443,BD阻塞原因分类,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747133970121,_widget_1747133970121,BD阻塞原因详细描述,textarea,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1749290572780,_widget_1749290572780,签约&上线负责人,user,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747123933310,_widget_1747123933310,客户签约日期,datetime,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747123933311,_widget_1747123933311,客户付款日期,datetime,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1749632087678,_widget_1749632087678,付款金额(泰铢),number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1749632087641,_widget_1749632087641,付款截图,image,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1749632087639,_widget_1749632087639,上传发票附件,upload,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1740460160201,_widget_1740460160201,上线状态,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747123933312,_widget_1747123933312,上线日期,datetime,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747133970122,_widget_1747133970122,上线失败原因,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1631071964934,_widget_1631071964934,上线失败原因描述,textarea,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1749108058561,_widget_1749108058561,门店系统使用情况说明,textarea,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1747123507416,_widget_1747123507416,开户门店ID,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013289,_widget_1737092013289,公司名称,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013291,_widget_1737092013291,主店简称,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013292,_widget_1737092013292,营业执照号,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013293,_widget_1737092013293,营业执照名称,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013300,_widget_1737092013300,门店logo,image,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013301,_widget_1737092013301,pc首页左上角logo,image,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013302,_widget_1737092013302,pc首页左上角logo缩略图,image,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013321,_widget_1737092013321,门头照片,image,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737097231480,_widget_1737097231480,府,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737097231482,_widget_1737097231482,县,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013299,_widget_1737092013299,地址(省市区),text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737097782393,_widget_1737097782393,详情地址,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013314,_widget_1737092013314,营业开始时间,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013313,_widget_1737092013313,营业结束时间,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013312,_widget_1737092013312,经度,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013311,_widget_1737092013311,纬度,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013310,_widget_1737092013310,负责人名字,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013308,_widget_1737092013308,负责人手机号,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013309,_widget_1737092013309,服务接待固话,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013315,_widget_1737092013315,服务接待名称,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013316,_widget_1737092013316,服务接待手机号,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013320,_widget_1737092013320,账号数上限,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013318,_widget_1737092013318,税号,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013317,_widget_1737092013317,分支编号,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013319,_widget_1737092013319,嘉实多内部门店编码,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013339,_widget_1737092013339,运营顾问(上线负责人),user,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013340,_widget_1737092013340,运营专家,user,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1737092013341,_widget_1737092013341,区域经理,user,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1750125550901,_widget_1750125550901,状态,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,673457d6837e60a418e0e56b,020100200000000000000001,
|
||||
_widget_1742174728275,_widget_1742174728275,指标归属日期,datetime,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963874,_widget_1742091963874,公司ID,text,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963875,_widget_1742091963875,公司名称,text,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963876,_widget_1742091963876,门店ID,text,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963877,_widget_1742091963877,门店名称,text,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963878,_widget_1742091963878,门店简称,text,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963879,_widget_1742091963879,门店创建时间,datetime,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963880,_widget_1742091963880,指标类型,combo,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963881,_widget_1742091963881,指标子类型,combo,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_1742091963882,_widget_1742091963882,指标值,number,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231,
|
||||
_widget_0201002000002,_widget_0201002000002,客户名称,company,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1630862543415,_widget_1630862543415,客户状态,combo,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1630862543637,_widget_1630862543637,所属行业,combo,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1646826421878,_widget_1646826421878,客户邮箱,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1631071964919,_widget_1631071964919,客户地址,address,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1631071964934,_widget_1631071964934,客户详情,textarea,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_0201002000003,_widget_0201002000003,销售负责人,user,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_0201002000004,_widget_0201002000004,协作人,usergroup,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,675a7f2a54c95e84fb66393e,020100200000000000000001,
|
||||
|
@@ -0,0 +1,529 @@
|
||||
name,widgetName,label,type,items,app_id,entry_id
|
||||
_widget_1690785229260,_widget_1690785229260,怎么称呼您,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229261,_widget_1690785229261,您门店或公司名称,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693382214358,_widget_1693382214358,您的联系方式,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785326597,_widget_1690785326597,地址,address,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229266,_widget_1690785229266,备注,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229284,_widget_1690785229284,客户概况,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690787826014,_widget_1690787826014,门头照片(可上传多张),image,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229278,_widget_1690785229278,意向书来源,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1741837239117,_widget_1741837239117,业务类型,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022904,_widget_1693381022904,客户渠道,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1715146829031,_widget_1715146829031,轻连锁类型,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229280,_widget_1690785229280,小六,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1694154771486,_widget_1694154771486,技术专家,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229281,_widget_1690785229281,战区经理,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1718855270618,_widget_1718855270618,该养车门店是否已退出?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1718855270620,_widget_1718855270620,退出情况说明,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1718855270621,_widget_1718855270621,该养车门店是否有F6系统需求?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229282,_widget_1690785229282,意向阶段,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693551051341,_widget_1693551051341,客户门店数,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229283,_widget_1690785229283,意向版本,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022909,_widget_1693381022909,客户沟通记录,subform,"[{'name': '_widget_1693381022911', 'widgetName': '_widget_1693381022911', 'label': '跟进日期', 'type': 'datetime'}, {'name': '_widget_1693381022912', 'widgetName': '_widget_1693381022912', 'label': '沟通方式', 'type': 'combo'}, {'name': '_widget_1693381022914', 'widgetName': '_widget_1693381022914', 'label': '沟通概要', 'type': 'textarea'}]",66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022908,_widget_1693381022908,下次跟进日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1696902504775,_widget_1696902504775,理论下次跟进日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1694398435902,_widget_1694398435902,最近一次沟通日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022915,_widget_1693381022915,客户在用系统名称,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022916,_widget_1693381022916,预计成交金额(单位:元),number,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022917,_widget_1693381022917,预计成交日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1699321775702,_widget_1699321775702,实际成交日期,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022918,_widget_1693381022918,下单手机号,phone,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022919,_widget_1693381022919,放弃原因分类,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022921,_widget_1693381022921,价格原因,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022923,_widget_1693381022923,产品原因,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022925,_widget_1693381022925,门店原因,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022930,_widget_1693381022930,加盟外部连锁,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022927,_widget_1693381022927,内部业务影响(包含接车宝会员宝安装服务),radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1724313867483,_widget_1724313867483,输单原因分类,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1723603567435,_widget_1723603567435,竞品名称,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1693381022929,_widget_1693381022929,输单/放弃说明,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626093,_widget_1708935626093,线索沟通情况,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709019633297,_widget_1709019633297,客户业务需求,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626085,_widget_1708935626085,客户手机号是否是微信号?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626087,_widget_1708935626087,企微是否已加好友?,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626089,_widget_1708935626089,BOSS系统里是否有该客户信息,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709027488072,_widget_1709027488072,客户BOSS业务信息,checkboxgroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626095,_widget_1708935626095,联系人身份,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709100220536,_widget_1709100220536,门店业务类型,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626104,_widget_1708935626104,客户门店工位数,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626100,_widget_1708935626100,客户是否有需求,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626102,_widget_1708935626102,客户主要需求功能模块(可多选),checkboxgroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626107,_widget_1708935626107,客户原系统,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626091,_widget_1708935626091,客户预算,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626098,_widget_1708935626098,预计使用时间,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709186927667,_widget_1709186927667,门头照片等,image,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709100220453,_widget_1709100220453,SDR联系记录,subform,"[{'name': '_widget_1709100220457', 'widgetName': '_widget_1709100220457', 'label': '日期时间', 'type': 'datetime'}, {'name': '_widget_1709100220455', 'widgetName': '_widget_1709100220455', 'label': '联系情况', 'type': 'text'}]",66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1708935626292,_widget_1708935626292,SDR判断客户是否需要进一步跟进,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1710292803370,_widget_1710292803370,SDR建议线索跟进时间,combo,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1710037836605,_widget_1710037836605,线索放弃说明,textarea,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709543713740,_widget_1709543713740,SDR放弃意见,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725501916821,_widget_1725501916821,提交时间,datetime,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725507662927,_widget_1725507662927,提交人,user,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229279,_widget_1690785229279,城市,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1692070536228,_widget_1692070536228,区,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1697423018006,_widget_1697423018006,战区,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1694076921201,_widget_1694076921201,线上线下,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709868059118,_widget_1709868059118,线索跟进角色,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1709781645383,_widget_1709781645383,客户跟进角色,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725875301461,_widget_1725875301461,技术支持提交人,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1725933630175,_widget_1725933630175,是否有效线索,text,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1690785229262,_widget_1690785229262,您的联系方式,phone,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_1723431564839,_widget_1723431564839,线索状态,radiogroup,,66b9678280b37f8a276b1d01,64c755cd97379b0008bf80dd
|
||||
_widget_0201002000002,_widget_0201002000002,经销商名称,company,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401220,_widget_1732095401220,经销商简称,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401222,_widget_1732095401222,营业执照号,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401223,_widget_1732095401223,营业执照名称,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235945,_widget_1732153235945,详细地址,address,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401224,_widget_1732095401224,负责人姓名,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401225,_widget_1732095401225,负责人手机号,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401226,_widget_1732095401226,联系电话,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1742200662775,_widget_1742200662775,购买年限,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1742278002584,_widget_1742278002584,购买版本,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732095401227,_widget_1732095401227,经销商可购买的群数量,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000003,_widget_0201002000003,销售负责人,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235954,_widget_1732153235954,运营顾问,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235955,_widget_1732153235955,运营专家,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732153235956,_widget_1732153235956,区域经理,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1741165766484,_widget_1741165766484,业务,user,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732180937809,_widget_1732180937809,经销商ID,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732180937812,_widget_1732180937812,开通状态,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732180937811,_widget_1732180937811,开通时间,datetime,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1741160451740,_widget_1741160451740,系统到期时间,datetime,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1630862543415,_widget_1630862543415,客户状态,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1646826421878,_widget_1646826421878,客户邮箱,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1630862543637,_widget_1630862543637,所属行业,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1732178180219,_widget_1732178180219,客户来源表单字段,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_0201002000004,_widget_0201002000004,协作人,usergroup,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1631071964934,_widget_1631071964934,客户详情,textarea,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,,673d8427549d00c3d753c530,020100200000000000000001
|
||||
_widget_1734062123070,_widget_1734062123070,门店名称,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123068,_widget_1734062123068,公司名称,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123071,_widget_1734062123071,门店编码,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123072,_widget_1734062123072,公司等级,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123073,_widget_1734062123073,门店类型,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123085,_widget_1734062123085,是否主店,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123067,_widget_1734062123067,公司id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123069,_widget_1734062123069,门店id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123169,_widget_1734062123169,经营模式,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123170,_widget_1734062123170,联系人,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123172,_widget_1734062123172,手机号码,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123179,_widget_1734062123179,是否主店,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123180,_widget_1734062123180,门店数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123066,_widget_1734062123066,日期,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123065,_widget_1734062123065,日期批次,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071375,_widget_1749000071375,日期(时间字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123192,_widget_1734062123192,是否加店,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123194,_widget_1734062123194,门店规模,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123196,_widget_1734062123196,经营范围,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123197,_widget_1734062123197,维修厂类型,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123199,_widget_1734062123199,工位数,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123201,_widget_1734062123201,门店阶段,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123203,_widget_1734062123203,门店分层,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1742890765211,_widget_1742890765211,门头照片,image,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123090,_widget_1734062123090,省,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123092,_widget_1734062123092,市,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123094,_widget_1734062123094,区,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123095,_widget_1734062123095,大区,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123097,_widget_1734062123097,小区,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123099,_widget_1734062123099,前置仓名称,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123102,_widget_1734062123102,区域经理,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123103,_widget_1734062123103,续约顾问,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123105,_widget_1734062123105,运营负责人,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123204,_widget_1734062123204,运营专家,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1748496855779,_widget_1748496855779,区域经理(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1748496855780,_widget_1748496855780,运营负责人(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1748496855778,_widget_1748496855778,续约顾问(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1751877712235,_widget_1751877712235,运营专家(成员字段),user,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123075,_widget_1734062123075,ERP操作模式,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123076,_widget_1734062123076,公众号,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123077,_widget_1734062123077,小程序,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123078,_widget_1734062123078,微信商城,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123079,_widget_1734062123079,洗车摄像头,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123106,_widget_1734062123106,有效账户数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123175,_widget_1734062123175,安装服务,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123184,_widget_1734062123184,SaaS版本,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123074,_widget_1734062123074,客户状态,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123081,_widget_1734062123081,开户日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123082,_widget_1734062123082,应续约日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123083,_widget_1734062123083,使用天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123084,_widget_1734062123084,使用年数,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123176,_widget_1734062123176,上线日期,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123177,_widget_1734062123177,过期日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123178,_widget_1734062123178,实际续约日,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071377,_widget_1749000071377,开户日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071382,_widget_1749000071382,应续约日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071384,_widget_1749000071384,上线日期(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071389,_widget_1749000071389,过期日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1749000071391,_widget_1749000071391,实际续约日(日期字段),datetime,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123111,_widget_1734062123111,G状态,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123115,_widget_1734062123115,活跃状态,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123117,_widget_1734062123117,近30天业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123119,_widget_1734062123119,近7天业务单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123120,_widget_1734062123120,近7天业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123122,_widget_1734062123122,UV数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123167,_widget_1734062123167,G变化(月),text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123173,_widget_1734062123173,G月份,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123174,_widget_1734062123174,G转化率,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123182,_widget_1734062123182,G变化类型,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123183,_widget_1734062123183,G流失天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123185,_widget_1734062123185,M-1(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123186,_widget_1734062123186,M-2(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123187,_widget_1734062123187,M-3(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123188,_widget_1734062123188,M-4(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123189,_widget_1734062123189,M-5(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123190,_widget_1734062123190,M-6(G),number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123191,_widget_1734062123191,G天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123202,_widget_1734062123202,本月G天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123116,_widget_1734062123116,近30天业务单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123155,_widget_1734062123155,近30天维修单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123156,_widget_1734062123156,近30天洗车单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123157,_widget_1734062123157,近30天维修开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123158,_widget_1734062123158,近30天洗车开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123159,_widget_1734062123159,近30天销售单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123160,_widget_1734062123160,近30天销售单开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123161,_widget_1734062123161,近30天采购单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123162,_widget_1734062123162,近30天采购开单天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123163,_widget_1734062123163,近30天卡业务单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123164,_widget_1734062123164,近30天卡业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123118,_widget_1734062123118,自然月业务天数,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123123,_widget_1734062123123,T_1开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123124,_widget_1734062123124,T_2开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123125,_widget_1734062123125,T_3开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123126,_widget_1734062123126,T_4开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123127,_widget_1734062123127,T_5开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123128,_widget_1734062123128,T_6开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123129,_widget_1734062123129,T_7开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123130,_widget_1734062123130,T_8开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123131,_widget_1734062123131,T_9开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123132,_widget_1734062123132,T_10开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123133,_widget_1734062123133,T_11开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123134,_widget_1734062123134,T_12开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123135,_widget_1734062123135,T_13开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123136,_widget_1734062123136,T_14开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123137,_widget_1734062123137,T_15开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123138,_widget_1734062123138,T_16开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123139,_widget_1734062123139,T_17开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123140,_widget_1734062123140,T_18开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123141,_widget_1734062123141,T_19开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123142,_widget_1734062123142,T_20开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123143,_widget_1734062123143,T_21开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123144,_widget_1734062123144,T_22开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123145,_widget_1734062123145,T_23开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123146,_widget_1734062123146,T_24开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123147,_widget_1734062123147,T_25开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123148,_widget_1734062123148,T_26开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123149,_widget_1734062123149,T_27开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123150,_widget_1734062123150,T_28开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123151,_widget_1734062123151,T_29开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123152,_widget_1734062123152,T_30开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123153,_widget_1734062123153,T_31开单量,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123080,_widget_1734062123080,is_maintenance_service,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123086,_widget_1734062123086,license_code,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123087,_widget_1734062123087,license_name,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123088,_widget_1734062123088,org_crm_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123089,_widget_1734062123089,province_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123091,_widget_1734062123091,city_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123093,_widget_1734062123093,area_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123096,_widget_1734062123096,region_short_name,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123098,_widget_1734062123098,carzone_store_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123100,_widget_1734062123100,customer_carzone_id,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123101,_widget_1734062123101,salesmen,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123104,_widget_1734062123104,impl_principal,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123107,_widget_1734062123107,active_user_type,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123108,_widget_1734062123108,limit_user_count,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123109,_widget_1734062123109,limit_user_type,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123110,_widget_1734062123110,is_n,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123112,_widget_1734062123112,is_v,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123113,_widget_1734062123113,is_visited,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123114,_widget_1734062123114,is_active,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123121,_widget_1734062123121,pv_count,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123154,_widget_1734062123154,etl_time,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123165,_widget_1734062123165,gd_sales_bill_count_last_30_day,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123166,_widget_1734062123166,gd_sales_bill_day_count_last_30_day,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123168,_widget_1734062123168,saas_package,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123171,_widget_1734062123171,contact_number,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123181,_widget_1734062123181,recent_bill_warning_days,number,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123193,_widget_1734062123193,pt,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123195,_widget_1734062123195,qualification_type_fmt,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123198,_widget_1734062123198,area,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123200,_widget_1734062123200,header_type_fmt,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1734062123205,_widget_1734062123205,tmall_maintain_service_status_desc,text,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1745908548852,_widget_1745908548852,江苏易捷门店归属公司,radiogroup,,675b900991ad2491c69389ca,675bb02bd2d53c2034c665e4
|
||||
_widget_1742795002375,_widget_1742795002375,公司ID,text,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002376,_widget_1742795002376,公众号名称,text,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002377,_widget_1742795002377,小程序模板类型,text,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002378,_widget_1742795002378,是否开通微信商城,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002379,_widget_1742795002379,上架商品数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002380,_widget_1742795002380,上架套餐卡数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002381,_widget_1742795002381,上架实体商品数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002382,_widget_1742795002382,上架项目数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002383,_widget_1742795002383,上架套餐数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002384,_widget_1742795002384,微信公众号粉丝数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002385,_widget_1742795002385,微信公众号绑定手机粉丝数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002386,_widget_1742795002386,是否开通微信小程序,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002387,_widget_1742795002387,微信小程序绑定用户数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002388,_widget_1742795002388,微信小程序绑定手机用户量,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002389,_widget_1742795002389,微信订单数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002390,_widget_1742795002390,微信支付订单量,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742795002391,_widget_1742795002391,线下订单数,number,,675b900991ad2491c69389ca,67e0f0fae622896749ba5087
|
||||
_widget_1742884710674,_widget_1742884710674,门店id,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884710675,_widget_1742884710675,提成类型_二级分类,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884710676,_widget_1742884710676,提成基数(本月),number,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884710677,_widget_1742884710677,提成基数(上月),number,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1748930441629,_widget_1748930441629,公司id,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1748931089356,_widget_1748931089356,门店编码,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1748931089357,_widget_1748931089357,门店名称,text,,675b900991ad2491c69389ca,67e24f665adf5a8611f3e589
|
||||
_widget_1742884829007,_widget_1742884829007,门店id,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1742884829008,_widget_1742884829008,商品名称,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1742884829009,_widget_1742884829009,服务期结束时间,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1748930826642,_widget_1748930826642,公司id,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1748931208852,_widget_1748931208852,门店编码,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1748931208851,_widget_1748931208851,门店名称,text,,675b900991ad2491c69389ca,67e24fdd8dfcfa918e17c30b
|
||||
_widget_1743065201885,_widget_1743065201885,公司id,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201886,_widget_1743065201886,是否启动短信功能,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201887,_widget_1743065201887,是否购买短信包,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201888,_widget_1743065201888,累计购买总数,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201889,_widget_1743065201889,累计发送成功总人数,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201890,_widget_1743065201890,剩余短信条数,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201891,_widget_1743065201891,第一次短信购买时间,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201892,_widget_1743065201892,最近一次短信购买时间,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201893,_widget_1743065201893,实付总金额,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1743065201894,_widget_1743065201894,短信剩余量是否小于20%,text,,675b900991ad2491c69389ca,67e5107198ba1b20d5df3974
|
||||
_widget_1748241895830,_widget_1748241895830,门店名称,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895831,_widget_1748241895831,联系人,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895839,_widget_1748241895839,开户时间,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895842,_widget_1748241895842,门店编码,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895832,_widget_1748241895832,联系方式,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895850,_widget_1748241895850,系统版本,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895844,_widget_1748241895844,公司名称,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808679,_widget_1748246808679,运营顾问,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808682,_widget_1748246808682,区域经理,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895846,_widget_1748241895846,公司等级,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808681,_widget_1748246808681,运营专家,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895853,_widget_1748241895853,操作模式E.L/E.S,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895829,_widget_1748241895829,活跃健康状态变化,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895833,_widget_1748241895833,初始日,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895834,_widget_1748241895834,推进日,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176640,_widget_1748512176640,异常跟进情况描述,textarea,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176641,_widget_1748512176641,异常变化原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176643,_widget_1748512176643,正常使用,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176645,_widget_1748512176645,门店原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176647,_widget_1748512176647,服务原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176649,_widget_1748512176649,产品原因,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176651,_widget_1748512176651,未正式切换,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176655,_widget_1748512176655,跟进状态,radiogroup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808678,_widget_1748246808678,当前跟进人,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748512176654,_widget_1748512176654,跟进时间,datetime,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1751273412737,_widget_1751273412737,是否跟进完成,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748246808680,_widget_1748246808680,区域客服,user,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895847,_widget_1748241895847,大区,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895848,_widget_1748241895848,省,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895855,_widget_1748241895855,城市,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895849,_widget_1748241895849,门店类型,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895851,_widget_1748241895851,saas客户类型,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748241895852,_widget_1748241895852,门店阶段,text,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1748247754304,_widget_1748247754304,关联数据,lookup,,675b900991ad2491c69389ca,68340de79f116c0b66b6b0cc
|
||||
_widget_1751250294777,_widget_1751250294777,姓名1,text,,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a
|
||||
_widget_1751505196330,_widget_1751505196330,图片,image,,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a
|
||||
_widget_1751507507755,_widget_1751507507755,定位,location,,6694d3c4fcb69ca9a111a6c4,6861f5772b0d3575e14eba4a
|
||||
_widget_1739951204545,_widget_1739951204545,表单类型,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804406,_widget_1739252804406,日期,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739258942667,_widget_1739258942667,账号,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804419,_widget_1739252804419,日分区,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804397,_widget_1739252804397,产品名称,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804407,_widget_1739252804407,联系手机号,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804409,_widget_1739252804409,使用时长,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804396,_widget_1739252804396,开户日,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804408,_widget_1739252804408,到期日,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804410,_widget_1739252804410,续约日,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804400,_widget_1739252804400,客户状态,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804413,_widget_1739252804413,近一周开单量,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804414,_widget_1739252804414,近一周是否活跃,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804415,_widget_1739252804415,G状态:近30天开单大于等于10天,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804416,_widget_1739252804416,当月开单天数,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804417,_widget_1739252804417,近30天开单天数,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1739252804418,_widget_1739252804418,当月G天数,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740036367181,_widget_1740036367181,派发日期,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740043340255,_widget_1740043340255,跟进人,user,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143304,_widget_1741252143304,是否联系上·新签,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143306,_widget_1741252143306,是否联系上·异常,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143308,_widget_1741252143308,是否联系上·续约商机,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741252143310,_widget_1741252143310,是否联系上·过期召回,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741256466947,_widget_1741256466947,未接通原因备注,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384110,_widget_1740721384110,省市区,address,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741312871468,_widget_1741312871468,省市区·续约,address,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384111,_widget_1740721384111,门店名称,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741312871469,_widget_1741312871469,门店名称·续约,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384112,_widget_1740721384112,负责人姓名,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1741312871470,_widget_1741312871470,负责人姓名·续约,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384122,_widget_1740721384122,回访人·新签,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384117,_widget_1740721384117,未开单原因·新签,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384125,_widget_1740721384125,是否愿意继续使用·新签,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384127,_widget_1740721384127,回访人·异常,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384128,_widget_1740721384128,未开单原因·异常,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384129,_widget_1740721384129,是否愿意继续使用·异常,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384131,_widget_1740721384131,回访人·续约商机,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384132,_widget_1740721384132,是否有转化SaaS意愿·续约商机,combo,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384133,_widget_1740721384133,系统使用情况·续约商机,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749088869175,_widget_1749088869175,SaaS转化结果·续约商机,radiogroup,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749088869177,_widget_1749088869177,转化SaaS订单号·续约商机,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749088869190,_widget_1749088869190,其他转化结果·续约商机,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384135,_widget_1740721384135,回访人·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384136,_widget_1740721384136,未续约单原因·过期召回,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740721384137,_widget_1740721384137,是否有续约意愿·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854370,_widget_1749090854370,沟通跟进结果·过期召回,radiogroup,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854372,_widget_1749090854372,转化SaaS订单号·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854373,_widget_1749090854373,接车宝续约订单号·过期召回,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1749090854374,_widget_1749090854374,其他召回情况说明·过期召回,textarea,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1751356539629,_widget_1751356539629,完成日期时间,datetime,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1751271771674,_widget_1751271771674,是否完成,text,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1751356033346,_widget_1751356033346,流水号,sn,,6717470a0b3975ef583c6df1,67174710da507490d8ac12c1
|
||||
_widget_1740042824214,_widget_1740042824214,客服人员,user,,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a
|
||||
_widget_1740117343937,_widget_1740117343937,开关,combo,,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a
|
||||
_widget_1740042824216,_widget_1740042824216,下次开始位置,text,,6717470a0b3975ef583c6df1,67b6f2462f9ac03b783d409a
|
||||
_widget_1740723898388,_widget_1740723898388,日期,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898389,_widget_1740723898389,产品名称,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898390,_widget_1740723898390,账号,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898391,_widget_1740723898391,联系手机号,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898392,_widget_1740723898392,开户日,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898393,_widget_1740723898393,使用时长,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898394,_widget_1740723898394,续约日,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898395,_widget_1740723898395,到期日,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898396,_widget_1740723898396,客户状态,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898397,_widget_1740723898397,近一周开单量,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898398,_widget_1740723898398,近一周是否活跃,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898399,_widget_1740723898399,G状态:近30天开单大于等于10天,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898400,_widget_1740723898400,当月开单天数,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898401,_widget_1740723898401,近30天开单天数,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898402,_widget_1740723898402,当月G天数,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898403,_widget_1740723898403,日分区,number,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898404,_widget_1740723898404,表单类型,text,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_1740723898405,_widget_1740723898405,派发日期,datetime,,6717470a0b3975ef583c6df1,67c156ba635191b64af8a110
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000002,_widget_0201002000002,门店名称,company,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1750126318263,_widget_1750126318263,门店名称(后台传值),text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108119,_widget_1746675108119,原系统名称,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749204198412,_widget_1749204198412,原系统情况描述,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1630862543637,_widget_1630862543637,门店类型,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108151,_widget_1746675108151,门店设备,combocheck,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108121,_widget_1746675108121,门店业务,combocheck,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108115,_widget_1746675108115,工位数,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747321321284,_widget_1747321321284,员工数,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1746675108123,_widget_1746675108123,系统操作人员,combocheck,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097782383,_widget_1737097782383,门店环境,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1630862543415,_widget_1630862543415,BD状态,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933309,_widget_1747123933309,客户BD日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1751366502797,_widget_1751366502797,意向程度,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747661411161,_widget_1747661411161,Test开始日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747661411178,_widget_1747661411178,Test天数,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747664949166,_widget_1747664949166,Test账号状态,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000003,_widget_0201002000003,BD负责人,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000004,_widget_0201002000004,BD协作人,usergroup,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747133970117,_widget_1747133970117,BD阻塞原因,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747669642443,_widget_1747669642443,BD阻塞原因分类,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747133970121,_widget_1747133970121,BD阻塞原因详细描述,textarea,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749290572780,_widget_1749290572780,签约&上线负责人,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933310,_widget_1747123933310,客户签约日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933311,_widget_1747123933311,客户付款日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749632087678,_widget_1749632087678,付款金额(泰铢),number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749632087641,_widget_1749632087641,付款截图,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749632087639,_widget_1749632087639,上传发票附件,upload,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1740460160201,_widget_1740460160201,上线状态,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123933312,_widget_1747123933312,上线日期,datetime,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747133970122,_widget_1747133970122,上线失败原因,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1631071964934,_widget_1631071964934,上线失败原因描述,textarea,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1749108058561,_widget_1749108058561,门店系统使用情况说明,textarea,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1747123507416,_widget_1747123507416,开户门店ID,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013289,_widget_1737092013289,公司名称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013291,_widget_1737092013291,主店简称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013292,_widget_1737092013292,营业执照号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013293,_widget_1737092013293,营业执照名称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013300,_widget_1737092013300,门店logo,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013301,_widget_1737092013301,pc首页左上角logo,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013302,_widget_1737092013302,pc首页左上角logo缩略图,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013321,_widget_1737092013321,门头照片,image,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097231480,_widget_1737097231480,府,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097231482,_widget_1737097231482,县,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013299,_widget_1737092013299,地址(省市区),text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737097782393,_widget_1737097782393,详情地址,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013314,_widget_1737092013314,营业开始时间,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013313,_widget_1737092013313,营业结束时间,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013312,_widget_1737092013312,经度,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013311,_widget_1737092013311,纬度,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013310,_widget_1737092013310,负责人名字,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013308,_widget_1737092013308,负责人手机号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013309,_widget_1737092013309,服务接待固话,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013315,_widget_1737092013315,服务接待名称,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013316,_widget_1737092013316,服务接待手机号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013320,_widget_1737092013320,账号数上限,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013318,_widget_1737092013318,税号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013317,_widget_1737092013317,分支编号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013319,_widget_1737092013319,嘉实多内部门店编码,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013339,_widget_1737092013339,运营顾问(上线负责人),user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013340,_widget_1737092013340,运营专家,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1737092013341,_widget_1737092013341,区域经理,user,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1750125550901,_widget_1750125550901,状态,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,,673457d6837e60a418e0e56b,020100200000000000000001
|
||||
_widget_1742174728275,_widget_1742174728275,指标归属日期,datetime,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963874,_widget_1742091963874,公司ID,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963875,_widget_1742091963875,公司名称,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963876,_widget_1742091963876,门店ID,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963877,_widget_1742091963877,门店名称,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963878,_widget_1742091963878,门店简称,text,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963879,_widget_1742091963879,门店创建时间,datetime,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963880,_widget_1742091963880,指标类型,combo,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963881,_widget_1742091963881,指标子类型,combo,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_1742091963882,_widget_1742091963882,指标值,number,,673457d6837e60a418e0e56b,67d636bb6212b7619a7a4231
|
||||
_widget_0201002000002,_widget_0201002000002,客户名称,company,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000001,_widget_0201002000001,客户编码,sn,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1630862543415,_widget_1630862543415,客户状态,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1631071964761,_widget_1631071964761,客户来源,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1630862543434,_widget_1630862543434,客户级别,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000005,_widget_0201002000005,所属公海,account_pool,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1663742427957,_widget_1663742427957,客户查重,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1630862543637,_widget_1630862543637,所属行业,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1646826421878,_widget_1646826421878,客户邮箱,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1631071964919,_widget_1631071964919,客户地址,address,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1631071964934,_widget_1631071964934,客户详情,textarea,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000003,_widget_0201002000003,销售负责人,user,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000006,_widget_0201002000006,销售归属部门,dept,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_0201002000004,_widget_0201002000004,协作人,usergroup,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1663742427909,_widget_1663742427909,客户查重:客户表内该客户数量,number,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110880998,_widget_1709110880998,结算期限,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881001,_widget_1709110881001,信用额度/元,number,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881002,_widget_1709110881002,发票抬头,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881003,_widget_1709110881003,发票税号,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881004,_widget_1709110881004,税种,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881007,_widget_1709110881007,增值税税率 %,number,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881008,_widget_1709110881008,开户电话,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881009,_widget_1709110881009,开户银行,combo,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
_widget_1709110881016,_widget_1709110881016,银行账户,text,,675a7f2a54c95e84fb66393e,020100200000000000000001
|
||||
|
@@ -0,0 +1,853 @@
|
||||
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
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
# start_time = datetime.datetime.now()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class RevisitAllInformation:
|
||||
"""
|
||||
日常回访手动触发
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.get_feature_usage = None
|
||||
self.saas_create_time = None
|
||||
self.index = None
|
||||
self.date_one = None
|
||||
self.data_NGV_S = None
|
||||
self.date_list = None
|
||||
self.Smart_detection = None
|
||||
self.service_remind = None
|
||||
self.NGV_data_list = None
|
||||
self.permissions_table = None
|
||||
self.staff_id_list = None
|
||||
self.json_list = []
|
||||
self.policy_recognition = None
|
||||
self.widget_list = None
|
||||
self.private_domain = None
|
||||
self.public_domain = None
|
||||
self.public_domain_list = None
|
||||
self.different_industries = None
|
||||
self.different_industries_list = None
|
||||
self.groupnotification = None
|
||||
|
||||
def calculate_date_one(self, start_offset=0):
|
||||
"""
|
||||
计算从当前日期(或指定偏移量的日期)开始,往前遍历遇到date_list中日期的次数。
|
||||
|
||||
参数:
|
||||
- start_offset: 从当前日期起始的天数偏移量,默认为0(即今天)。负数表示过去,正数表示未来。
|
||||
|
||||
返回:
|
||||
- date_one: 遍历到date_list中日期的次数。
|
||||
"""
|
||||
jdy_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
jdy_start_time = datetime.datetime.now().strftime("%Y-%m-%d ")
|
||||
# 设置起始日期
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=start_offset)
|
||||
|
||||
# 初始化计数器
|
||||
date_one = 1
|
||||
print("当前日期:", now_time.strftime("%Y-%m-%d"))
|
||||
# 检查起始日期是否在date_list中
|
||||
if now_time.strftime("%Y-%m-%d") in self.date_list:
|
||||
date_one = 0
|
||||
print("开始次数:", date_one)
|
||||
|
||||
else:
|
||||
# 遍历日期
|
||||
for i in range(1, 10):
|
||||
new_date = now_time + datetime.timedelta(days=-i)
|
||||
new_date_str = new_date.strftime("%Y-%m-%d")
|
||||
print("遍历日期:", new_date_str)
|
||||
if new_date_str in self.date_list:
|
||||
date_one += 1
|
||||
print("节假日期:", new_date_str)
|
||||
else:
|
||||
break
|
||||
|
||||
print("遍历次数:", date_one)
|
||||
return date_one
|
||||
|
||||
@staticmethod
|
||||
def download_url_content(url, save_path):
|
||||
"""
|
||||
下载指定 URL 的内容并保存到本地文件。
|
||||
|
||||
:param url: 要下载内容的 URL
|
||||
:param save_path: 保存文件的路径
|
||||
"""
|
||||
try:
|
||||
# 发送 GET 请求以获取内容
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status() # 如果响应状态码不是 200,抛出异常
|
||||
|
||||
# 确保保存目录存在
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
|
||||
# 将内容写入文件
|
||||
with open(save_path, 'wb') as file:
|
||||
for chunk in response.iter_content(chunk_size=8192): # 分块写入,避免占用过多内存
|
||||
if chunk: # 过滤掉空块
|
||||
file.write(chunk)
|
||||
|
||||
print(f"文件已成功保存到 {save_path}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"下载失败: {e}")
|
||||
except Exception as e:
|
||||
print(f"发生错误: {e}")
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 省市区人员关系表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676512ac3e54dc3159460c0a"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.json_list = json_dict.get("data")
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取权限表信息
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b96c14e839f90fef1647c"}
|
||||
self.permissions_table = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取NGV数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
|
||||
self.NGV_data_list = api_instance.entry_data_list(payload).get("data", [])
|
||||
# print("NGV获取后的类型:", type(self.NGV_data_list))
|
||||
|
||||
# 获取服务提醒-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb7bda3029720f1083e99"}
|
||||
self.service_remind = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取智能检测-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb99649ab3ac975af6e39"}
|
||||
self.Smart_detection = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取功能使用情况表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6763bbf657bd8fb76fcb41b2"}
|
||||
self.get_feature_usage = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取保单识别表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6773a60d30ed87ff9f68d3c5"}
|
||||
self.policy_recognition = api_instance.entry_data_list(payload).get("data")
|
||||
# 提取 _widget_1735632397600 的值并存储在列表中
|
||||
self.widget_list = [item['_widget_1735632397600'] for item in self.policy_recognition]
|
||||
|
||||
# 获取私域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0f0fae622896749ba5087"}
|
||||
self.private_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742795002375 的值并存储在列表中
|
||||
# self.private_domain = [item['_widget_1742795002375'] for item in self.private_domain]
|
||||
|
||||
# 获取公域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0c702c8f603b997980999"}
|
||||
self.public_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.public_domain_list = [item['_widget_1742784257506'] for item in self.public_domain]
|
||||
|
||||
# 获取异业合作-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e24fdd8dfcfa918e17c30b"}
|
||||
self.different_industries = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.different_industries_list = [item['_widget_1742884829007'] for item in self.different_industries]
|
||||
|
||||
# 获取短信-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e5107198ba1b20d5df3974"}
|
||||
self.groupnotification = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
|
||||
@staticmethod
|
||||
def build_index(json_list):
|
||||
index = {}
|
||||
# print(json_list)
|
||||
for json_item in json_list:
|
||||
# json_item = json_item.get("data")
|
||||
# print(json_item)
|
||||
try:
|
||||
key = (json_item['_widget_1734677164861'], json_item['_widget_1734677164862'],
|
||||
json_item['_widget_1734677164863']) # 省市区
|
||||
if '_widget_1734677164871' not in json_item: # 日常回访客服
|
||||
raise KeyError("缺少 '日常回访客服' 键")
|
||||
index[key] = json_item
|
||||
except KeyError as e:
|
||||
print(f"警告:{e},跳过该条记录: {json_item}")
|
||||
continue
|
||||
return index
|
||||
|
||||
@staticmethod
|
||||
def find_customer_service(province_name, city_name, area_name, index):
|
||||
key = (province_name, city_name, area_name)
|
||||
# print(index)
|
||||
if key not in index:
|
||||
return "数据缺失: 未找到对应的日常回访客服"
|
||||
|
||||
return index[key]
|
||||
|
||||
@staticmethod
|
||||
def remove_parentheses(text: str) -> str:
|
||||
# 使用正则表达式匹配并去除括号及其内容
|
||||
# \s* 表示匹配零个或多个空白字符(处理括号前后可能存在的空格)
|
||||
# $ 和 $ 分别表示匹配左括号和右括号
|
||||
# 中间的 .*? 表示非贪婪地匹配任意数量的字符(包括没有字符的情况)
|
||||
cleaned_text = re.sub(r'\s*$.*?$\s*', '', text)
|
||||
# 为了确保同时处理中文括号,再进行一次替换
|
||||
cleaned_text = re.sub(r'\s*(.*?)\s*', '', cleaned_text)
|
||||
return cleaned_text.strip() # 去除两端多余的空白字符
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
return None
|
||||
|
||||
def assign_customer_service(self, province_name, city_name, area_name, index):
|
||||
"""根据省市区派发给日常回访客服"""
|
||||
try:
|
||||
customer_service_info = self.find_customer_service(province_name, city_name, area_name, index)
|
||||
|
||||
# 定义一个辅助函数,用于安全地获取多层字段中的 username
|
||||
def safe_get_username(data, key):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
return data.get(key, {}).get('username', "")
|
||||
return ""
|
||||
except:
|
||||
return ""
|
||||
|
||||
relationship_manager = safe_get_username(customer_service_info, '_widget_1734677164864')
|
||||
customer_service = safe_get_username(customer_service_info, '_widget_1734677164871')
|
||||
technician = safe_get_username(customer_service_info, '_widget_1734677164866')
|
||||
area_manager = safe_get_username(customer_service_info, '_widget_1734677164865')
|
||||
return relationship_manager, customer_service, technician, area_manager
|
||||
except Exception as e:
|
||||
print(f"Error finding customer service: {e}")
|
||||
return "分配失败,请检查", "分配失败,请检查", "分配失败,请检查"
|
||||
|
||||
def main(self):
|
||||
|
||||
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
global png_url, key, upload_key
|
||||
self.load_all_data()
|
||||
|
||||
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 # 新签日期
|
||||
|
||||
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)
|
||||
|
||||
data_NGV = self.data_NGV_S.copy()
|
||||
|
||||
def replace_values(series):
|
||||
# 使用条件判断来进行替换
|
||||
return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
|
||||
|
||||
# 对整个DataFrame的所有列应用替换函数
|
||||
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_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")
|
||||
|
||||
# 找到每组中 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])
|
||||
|
||||
# 找到每组中 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')
|
||||
)
|
||||
|
||||
# 将最佳值合并回原数据集
|
||||
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: 过滤条件
|
||||
|
||||
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']]
|
||||
|
||||
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)
|
||||
|
||||
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 = 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}, # 跟进人是技术专家
|
||||
})
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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},
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
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"]: # 下次是否推荐 功能使用情况表
|
||||
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"]: # 下次是否跟进
|
||||
print(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": "是"}})
|
||||
|
||||
break
|
||||
|
||||
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"
|
||||
] # 智能检测 是否使用
|
||||
|
||||
# 初始化默认值为"否"
|
||||
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:是否拥有
|
||||
else:
|
||||
payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
|
||||
except Exception as e:
|
||||
print(f"私域小程序:Error finding customer service: {e}")
|
||||
|
||||
# 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
|
||||
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:
|
||||
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}")
|
||||
|
||||
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")
|
||||
|
||||
distribution_date = datetime.datetime.now(datetime.timezone.utc)
|
||||
distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
|
||||
|
||||
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'
|
||||
|
||||
RevisitAllInformation.download_url_content(png_url, 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")
|
||||
# print("已上传文件")
|
||||
# print(upload_result)
|
||||
|
||||
# print(upload_key)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# 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, "手动添加日常回访")
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = RevisitAllInformation()
|
||||
start.main()
|
||||
@@ -0,0 +1,547 @@
|
||||
from api import API
|
||||
from back_ground_module import CommonModule
|
||||
import datetime
|
||||
import re
|
||||
import pandas as pd
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
start_time = datetime.datetime.now()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class KeyCustomerRevisit:
|
||||
"""大客户回访"""
|
||||
def __init__(self):
|
||||
self.index = None
|
||||
self.data_NGV = None
|
||||
self.date_list = None
|
||||
self.Smart_detection = None
|
||||
self.service_remind = None
|
||||
self.json_list = []
|
||||
self.NGV_data_list = None
|
||||
self.permissions_table = None
|
||||
self.staff_id_list = None
|
||||
self.get_feature_usage = None
|
||||
self.policy_recognition = None
|
||||
self.widget_list = None
|
||||
self.private_domain = None
|
||||
self.public_domain = None
|
||||
self.public_domain_list = None
|
||||
self.different_industries = None
|
||||
self.different_industries_list = None
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 省市区人员关系表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676512ac3e54dc3159460c0a"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.json_list = json_dict.get("data")
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取权限表信息
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b96c14e839f90fef1647c"}
|
||||
self.permissions_table = api_instance.entry_data_list(payload).get("data")
|
||||
|
||||
# 获取NGV数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
|
||||
self.NGV_data_list = api_instance.entry_data_list(payload).get("data")
|
||||
# print("NGV获取后的类型:", type(self.NGV_data_list))
|
||||
|
||||
# 获取服务提醒-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb7bda3029720f1083e99"}
|
||||
self.service_remind = api_instance.entry_data_list(payload).get("data")
|
||||
|
||||
# 获取智能检测-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb99649ab3ac975af6e39"}
|
||||
self.Smart_detection = api_instance.entry_data_list(payload).get("data")
|
||||
|
||||
# 获取功能使用情况表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6763bbf657bd8fb76fcb41b2"}
|
||||
self.get_feature_usage = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取保单识别表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6773a60d30ed87ff9f68d3c5"}
|
||||
self.policy_recognition = api_instance.entry_data_list(payload).get("data")
|
||||
# 提取 _widget_1735632397600 的值并存储在列表中
|
||||
self.widget_list = [item['_widget_1735632397600'] for item in self.policy_recognition]
|
||||
|
||||
# 获取私域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0f0fae622896749ba5087"}
|
||||
self.private_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742795002375 的值并存储在列表中
|
||||
self.private_domain = [item['_widget_1742795002375'] for item in self.private_domain]
|
||||
|
||||
# 获取公域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0c702c8f603b997980999"}
|
||||
self.public_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.public_domain_list = [item['_widget_1742784257506'] for item in self.private_domain]
|
||||
|
||||
# 获取异业合作-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e24fdd8dfcfa918e17c30b"}
|
||||
self.different_industries = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.different_industries_list = [item['_widget_1742784257506'] for item in self.different_industries]
|
||||
|
||||
|
||||
@staticmethod
|
||||
def remove_parentheses(text: str) -> str:
|
||||
# 使用正则表达式匹配并去除括号及其内容
|
||||
# \s* 表示匹配零个或多个空白字符(处理括号前后可能存在的空格)
|
||||
# $ 和 $ 分别表示匹配左括号和右括号
|
||||
# 中间的 .*? 表示非贪婪地匹配任意数量的字符(包括没有字符的情况)
|
||||
cleaned_text = re.sub(r'\s*$.*?$\s*', '', text)
|
||||
# 为了确保同时处理中文括号,再进行一次替换
|
||||
cleaned_text = re.sub(r'\s*(.*?)\s*', '', cleaned_text)
|
||||
return cleaned_text.strip() # 去除两端多余的空白字符
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
return None
|
||||
|
||||
def main(self):
|
||||
task_start_time =datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self.load_all_data()
|
||||
|
||||
self.date_list = common_module.get_holiday_list() # 获取一年中的节假日
|
||||
self.data_NGV = common_module.get_ngv_details(days_back=1) # 获取data_NGV 并转为str
|
||||
# self.index = self.build_index(self.json_list)
|
||||
|
||||
data_NGV = self.data_NGV.copy()
|
||||
|
||||
def replace_values(series):
|
||||
# 使用条件判断来进行替换
|
||||
return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
|
||||
|
||||
# 对整个DataFrame的所有列应用替换函数
|
||||
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_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")
|
||||
|
||||
# 找到每组中 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])
|
||||
|
||||
# 找到每组中 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')
|
||||
)
|
||||
|
||||
# 将最佳值合并回原数据集
|
||||
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: 过滤条件
|
||||
|
||||
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['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
|
||||
data_NGV['group_grade'].isin(['全国KA(FMVP)', '区域KA(MVP)'])) & (data_NGV['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_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')
|
||||
|
||||
data_NGV['条件'] = (data_NGV['org_type'] == "一般") & (data_NGV['org_status'] == '留存') & (
|
||||
data_NGV['group_grade'].isin(['全国KA(FMVP)', '区域KA(MVP)'])) & (data_NGV['is_main_org'] == 1)
|
||||
|
||||
data_NGV = data_NGV.loc[data_NGV["条件"]]
|
||||
|
||||
data_NGV = pd.concat([data_NGV, result], axis=0)
|
||||
|
||||
# 重置索引
|
||||
data_NGV = data_NGV.reset_index(drop=True)
|
||||
print(f'读取NGV大客户回访 {len(data_NGV)} 条数据!')
|
||||
# data_NGV.to_csv("大客户回访数据.csv")
|
||||
data_NGV = data_NGV.copy()
|
||||
|
||||
for index_num, row in data_NGV.iterrows(): # 对过滤后的每一条进行派发
|
||||
print(row["org_code"]) # 数据验证
|
||||
print(row["service_impl_principal"])
|
||||
print(row["area_manager"])
|
||||
print(row["technician"])
|
||||
print(row["group_grade"])
|
||||
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
|
||||
|
||||
relationship_manager, area_manager, technician, salesmen = [NGV_roles[role] for role in
|
||||
['relationship_manager', 'area_manager',
|
||||
'technician', 'salesmen']]
|
||||
|
||||
payload_dict.update({
|
||||
"_widget_1734590278288": {"value": technician} # 跟进人是技术专家
|
||||
})
|
||||
|
||||
payload_dict.update({
|
||||
"_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
|
||||
"_widget_1734590278290": {"value": area_manager}, # 区域经理
|
||||
"_widget_1734590278291": {"value": technician}, # 技术专家
|
||||
"_widget_1735290738545": {"value": salesmen}} # 销售负责人
|
||||
)
|
||||
|
||||
# 输出结果
|
||||
print("SaaS开户回访人员:", relationship_manager or "未分配")
|
||||
print("SaaS技术专家:", technician or "未分配")
|
||||
print("SaaS区域经理:", area_manager or "未分配")
|
||||
|
||||
# 判断权限唯一值
|
||||
pattern = r'(.+)\('
|
||||
match = re.search(pattern, row['max_group_grade'])
|
||||
group_grade = match.group(1)
|
||||
|
||||
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)
|
||||
data_NGV.at[index_num, 'NGV_store_level_key'] = 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"]: # 下次是否推荐 功能使用情况表
|
||||
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"]: # 下次是否跟进
|
||||
print(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": "是"}})
|
||||
|
||||
break
|
||||
if row["active_status_fmt"] == "活跃": # 开单 是否使用
|
||||
payload_dict.update({"_widget_1735004315765": {"value": "是"}})
|
||||
else:
|
||||
payload_dict.update({"_widget_1735004315765": {"value": "否"}})
|
||||
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"
|
||||
] # 智能检测 是否使用
|
||||
|
||||
# 初始化默认值为"否"
|
||||
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:
|
||||
if row["id_own_group"] in self.private_domain:
|
||||
payload_dict.update({'_widget_1735106258143': {"value": "是"}}) # SYXCX:是否使用
|
||||
else:
|
||||
payload_dict.update({'_widget_1735106258143': {"value": "否"}}) # SYXCX:是否使用
|
||||
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:是否拥有
|
||||
else:
|
||||
payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
|
||||
except Exception as e:
|
||||
print(f"私域小程序:Error finding customer service: {e}")
|
||||
|
||||
# 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
|
||||
try:
|
||||
for item in self.public_domain:
|
||||
if row["id_own_org"] == item.get("_widget_1742784257506"): # 门店id
|
||||
if int(item.get("_widget_1742784257509")) > 0 : # 发布商品数量
|
||||
payload_dict.update({"_widget_1735106258114": {"value": "是"}}) # GYXCX:是否使用
|
||||
break
|
||||
else :
|
||||
payload_dict.update({"_widget_1735106258114": {"value": "否"}}) # GYXCX:是否使用
|
||||
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}")
|
||||
|
||||
|
||||
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)
|
||||
if not NGV_data_id:
|
||||
print("未找到数据ID")
|
||||
|
||||
distribution_date = datetime.datetime.now(datetime.timezone.utc)
|
||||
distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
|
||||
|
||||
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": "2025第一季度大客户回访"}, # 跟进阶段
|
||||
"_widget_1734321349021": {"value": NGV_data_id}, # 关data_get联数据
|
||||
"_widget_1742548684369": {"value": "定期维护,了解业务变化,保持客户满意度的同时挖掘增购机会。"}, # 主要目的
|
||||
"_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}, # 派发时间
|
||||
})
|
||||
|
||||
routine_follow_up_payload = {
|
||||
"api_key": "675b900991ad2491c69389ca",
|
||||
"entry_id": "675b9c63925cd404038a6b86",
|
||||
"is_start_workflow": "true",
|
||||
"data": payload_dict,
|
||||
}
|
||||
|
||||
print(routine_follow_up_payload)
|
||||
|
||||
res = api_instance.data_batch_create(routine_follow_up_payload)
|
||||
logger.info(f"创建结果:{res}")
|
||||
print(res)
|
||||
|
||||
# data_NGV.to_csv("final_data_NGV.csv", index=False)
|
||||
common_module.send_task_status(task_start_time, "大客户回访")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = KeyCustomerRevisit()
|
||||
start.main()
|
||||
@@ -0,0 +1,852 @@
|
||||
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
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
# start_time = datetime.datetime.now()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class NewServicesRevisit:
|
||||
"""
|
||||
新签回访180天
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.get_feature_usage = None
|
||||
self.saas_create_time = None
|
||||
self.index = None
|
||||
self.date_one = None
|
||||
self.data_NGV_S = None
|
||||
self.date_list = None
|
||||
self.Smart_detection = None
|
||||
self.service_remind = None
|
||||
self.NGV_data_list = None
|
||||
self.permissions_table = None
|
||||
self.staff_id_list = None
|
||||
self.json_list = []
|
||||
self.policy_recognition = None
|
||||
self.widget_list = None
|
||||
self.private_domain = None
|
||||
self.public_domain = None
|
||||
self.public_domain_list = None
|
||||
self.different_industries = None
|
||||
self.different_industries_list = None
|
||||
self.groupnotification = None
|
||||
|
||||
def calculate_date_one(self, start_offset=0):
|
||||
"""
|
||||
计算从当前日期(或指定偏移量的日期)开始,往前遍历遇到date_list中日期的次数。
|
||||
|
||||
参数:
|
||||
- start_offset: 从当前日期起始的天数偏移量,默认为0(即今天)。负数表示过去,正数表示未来。
|
||||
|
||||
返回:
|
||||
- date_one: 遍历到date_list中日期的次数。
|
||||
"""
|
||||
jdy_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
jdy_start_time = datetime.datetime.now().strftime("%Y-%m-%d ")
|
||||
# 设置起始日期
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=start_offset)
|
||||
|
||||
# 初始化计数器
|
||||
date_one = 1
|
||||
print("当前日期:", now_time.strftime("%Y-%m-%d"))
|
||||
# 检查起始日期是否在date_list中
|
||||
if now_time.strftime("%Y-%m-%d") in self.date_list:
|
||||
date_one = 0
|
||||
print("开始次数:", date_one)
|
||||
|
||||
else:
|
||||
# 遍历日期
|
||||
for i in range(1, 10):
|
||||
new_date = now_time + datetime.timedelta(days=-i)
|
||||
new_date_str = new_date.strftime("%Y-%m-%d")
|
||||
print("遍历日期:", new_date_str)
|
||||
if new_date_str in self.date_list:
|
||||
date_one += 1
|
||||
print("节假日期:", new_date_str)
|
||||
else:
|
||||
break
|
||||
|
||||
print("遍历次数:", date_one)
|
||||
return date_one
|
||||
|
||||
@staticmethod
|
||||
def download_url_content(url, save_path):
|
||||
"""
|
||||
下载指定 URL 的内容并保存到本地文件。
|
||||
|
||||
:param url: 要下载内容的 URL
|
||||
:param save_path: 保存文件的路径
|
||||
"""
|
||||
try:
|
||||
# 发送 GET 请求以获取内容
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status() # 如果响应状态码不是 200,抛出异常
|
||||
|
||||
# 确保保存目录存在
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
|
||||
# 将内容写入文件
|
||||
with open(save_path, 'wb') as file:
|
||||
for chunk in response.iter_content(chunk_size=8192): # 分块写入,避免占用过多内存
|
||||
if chunk: # 过滤掉空块
|
||||
file.write(chunk)
|
||||
|
||||
print(f"文件已成功保存到 {save_path}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"下载失败: {e}")
|
||||
except Exception as e:
|
||||
print(f"发生错误: {e}")
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 省市区人员关系表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676512ac3e54dc3159460c0a"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.json_list = json_dict.get("data")
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取权限表信息
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b96c14e839f90fef1647c"}
|
||||
self.permissions_table = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取NGV数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
|
||||
self.NGV_data_list = api_instance.entry_data_list(payload).get("data", [])
|
||||
# print("NGV获取后的类型:", type(self.NGV_data_list))
|
||||
|
||||
# 获取服务提醒-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb7bda3029720f1083e99"}
|
||||
self.service_remind = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取智能检测-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb99649ab3ac975af6e39"}
|
||||
self.Smart_detection = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取功能使用情况表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6763bbf657bd8fb76fcb41b2"}
|
||||
self.get_feature_usage = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取保单识别表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6773a60d30ed87ff9f68d3c5"}
|
||||
self.policy_recognition = api_instance.entry_data_list(payload).get("data")
|
||||
# 提取 _widget_1735632397600 的值并存储在列表中
|
||||
self.widget_list = [item['_widget_1735632397600'] for item in self.policy_recognition]
|
||||
|
||||
# 获取私域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0f0fae622896749ba5087"}
|
||||
self.private_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742795002375 的值并存储在列表中
|
||||
# self.private_domain = [item['_widget_1742795002375'] for item in self.private_domain]
|
||||
|
||||
# 获取公域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0c702c8f603b997980999"}
|
||||
self.public_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.public_domain_list = [item['_widget_1742784257506'] for item in self.public_domain]
|
||||
|
||||
# 获取异业合作-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e24fdd8dfcfa918e17c30b"}
|
||||
self.different_industries = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.different_industries_list = [item['_widget_1742884829007'] for item in self.different_industries]
|
||||
|
||||
# 获取短信-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e5107198ba1b20d5df3974"}
|
||||
self.groupnotification = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
@staticmethod
|
||||
def build_index(json_list):
|
||||
index = {}
|
||||
# print(json_list)
|
||||
for json_item in json_list:
|
||||
# json_item = json_item.get("data")
|
||||
# print(json_item)
|
||||
try:
|
||||
key = (json_item['_widget_1734677164861'], json_item['_widget_1734677164862'],
|
||||
json_item['_widget_1734677164863']) # 省市区
|
||||
if '_widget_1734677164871' not in json_item: # 日常回访客服
|
||||
raise KeyError("缺少 '日常回访客服' 键")
|
||||
index[key] = json_item
|
||||
except KeyError as e:
|
||||
print(f"警告:{e},跳过该条记录: {json_item}")
|
||||
continue
|
||||
return index
|
||||
|
||||
@staticmethod
|
||||
def find_customer_service(province_name, city_name, area_name, index):
|
||||
key = (province_name, city_name, area_name)
|
||||
# print(index)
|
||||
if key not in index:
|
||||
return "数据缺失: 未找到对应的日常回访客服"
|
||||
|
||||
return index[key]
|
||||
|
||||
@staticmethod
|
||||
def remove_parentheses(text: str) -> str:
|
||||
# 使用正则表达式匹配并去除括号及其内容
|
||||
# \s* 表示匹配零个或多个空白字符(处理括号前后可能存在的空格)
|
||||
# $ 和 $ 分别表示匹配左括号和右括号
|
||||
# 中间的 .*? 表示非贪婪地匹配任意数量的字符(包括没有字符的情况)
|
||||
cleaned_text = re.sub(r'\s*$.*?$\s*', '', text)
|
||||
# 为了确保同时处理中文括号,再进行一次替换
|
||||
cleaned_text = re.sub(r'\s*(.*?)\s*', '', cleaned_text)
|
||||
return cleaned_text.strip() # 去除两端多余的空白字符
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
return None
|
||||
|
||||
def assign_customer_service(self, province_name, city_name, area_name, index):
|
||||
"""根据省市区派发给日常回访客服"""
|
||||
try:
|
||||
customer_service_info = self.find_customer_service(province_name, city_name, area_name, index)
|
||||
|
||||
# 定义一个辅助函数,用于安全地获取多层字段中的 username
|
||||
def safe_get_username(data, key):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
return data.get(key, {}).get('username', "")
|
||||
return ""
|
||||
except:
|
||||
return ""
|
||||
|
||||
relationship_manager = safe_get_username(customer_service_info, '_widget_1734677164864')
|
||||
customer_service = safe_get_username(customer_service_info, '_widget_1734677164871')
|
||||
technician = safe_get_username(customer_service_info, '_widget_1734677164866')
|
||||
area_manager = safe_get_username(customer_service_info, '_widget_1734677164865')
|
||||
return relationship_manager, customer_service, technician, area_manager
|
||||
except Exception as e:
|
||||
print(f"Error finding customer service: {e}")
|
||||
return "分配失败,请检查", "分配失败,请检查", "分配失败,请检查"
|
||||
|
||||
def main(self):
|
||||
|
||||
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
global png_url, key, upload_key
|
||||
self.load_all_data()
|
||||
|
||||
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 # 新签日期
|
||||
|
||||
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)
|
||||
|
||||
data_NGV = self.data_NGV_S.copy()
|
||||
|
||||
def replace_values(series):
|
||||
# 使用条件判断来进行替换
|
||||
return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
|
||||
|
||||
# 对整个DataFrame的所有列应用替换函数
|
||||
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_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")
|
||||
|
||||
# 找到每组中 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])
|
||||
|
||||
# 找到每组中 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')
|
||||
)
|
||||
|
||||
# 将最佳值合并回原数据集
|
||||
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: 过滤条件
|
||||
|
||||
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']]
|
||||
|
||||
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)
|
||||
|
||||
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['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}, # 跟进人是技术专家
|
||||
})
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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},
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
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"]: # 下次是否推荐 功能使用情况表
|
||||
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"]: # 下次是否跟进
|
||||
print(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": "是"}})
|
||||
|
||||
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"
|
||||
] # 智能检测 是否使用
|
||||
|
||||
# 初始化默认值为"否"
|
||||
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:是否拥有
|
||||
else:
|
||||
payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
|
||||
except Exception as e:
|
||||
print(f"私域小程序:Error finding customer service: {e}")
|
||||
|
||||
# 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
|
||||
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:
|
||||
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}")
|
||||
|
||||
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")
|
||||
|
||||
distribution_date = datetime.datetime.now(datetime.timezone.utc)
|
||||
distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
|
||||
|
||||
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'
|
||||
|
||||
NewServicesRevisit.download_url_content(png_url, 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")
|
||||
# print("已上传文件")
|
||||
# print(upload_result)
|
||||
|
||||
# print(upload_key)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
print(routine_follow_up_payload)
|
||||
|
||||
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, "新签客户回访")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = NewServicesRevisit()
|
||||
start.main()
|
||||
@@ -0,0 +1,946 @@
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
from api import API
|
||||
from back_ground_module import CommonModule
|
||||
import pandas as pd
|
||||
import datetime
|
||||
import re
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
# start_time = datetime.datetime.now()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class RenewServicesRevisit:
|
||||
"""续约回访90-180"""
|
||||
|
||||
def __init__(self):
|
||||
self.index = None
|
||||
self.data_NGV = None
|
||||
self.date_list = None
|
||||
self.Smart_detection = None
|
||||
self.service_remind = None
|
||||
self.json_list = []
|
||||
self.NGV_data_list = None
|
||||
self.permissions_table = None
|
||||
self.staff_id_list = None
|
||||
self.get_feature_usage = None
|
||||
self.policy_recognition = None
|
||||
self.widget_list = None
|
||||
self.private_domain = None
|
||||
self.public_domain = None
|
||||
self.public_domain_list = None
|
||||
self.different_industries = None
|
||||
self.different_industries_list = None
|
||||
self.groupnotification = None
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 省市区人员关系表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676512ac3e54dc3159460c0a"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
if json_dict and "data" in json_dict:
|
||||
self.json_list = json_dict.get("data")
|
||||
else:
|
||||
print("加载省市区人员关系表失败")
|
||||
self.json_list = []
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取权限表信息
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b96c14e839f90fef1647c"}
|
||||
self.permissions_table = api_instance.entry_data_list(payload).get("data")
|
||||
|
||||
# 获取NGV数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
|
||||
self.NGV_data_list = api_instance.entry_data_list(payload).get("data")
|
||||
# print("NGV获取后的类型:", type(self.NGV_data_list))
|
||||
|
||||
# 获取服务提醒-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb7bda3029720f1083e99"}
|
||||
self.service_remind = api_instance.entry_data_list(payload).get("data")
|
||||
|
||||
# 获取智能检测-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb99649ab3ac975af6e39"}
|
||||
self.Smart_detection = api_instance.entry_data_list(payload).get("data")
|
||||
|
||||
# 获取功能使用情况表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6763bbf657bd8fb76fcb41b2"}
|
||||
self.get_feature_usage = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取保单识别表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6773a60d30ed87ff9f68d3c5"}
|
||||
self.policy_recognition = api_instance.entry_data_list(payload).get("data")
|
||||
# 提取 _widget_1735632397600 的值并存储在列表中
|
||||
self.widget_list = [item['_widget_1735632397600'] for item in self.policy_recognition]
|
||||
|
||||
# 获取私域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0f0fae622896749ba5087"}
|
||||
self.private_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742795002375 的值并存储在列表中
|
||||
# self.private_domain_list = [item['_widget_1742795002375'] for item in self.private_domain]
|
||||
|
||||
# 获取公域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0c702c8f603b997980999"}
|
||||
self.public_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.public_domain_list = [item['_widget_1742784257506'] for item in self.public_domain]
|
||||
|
||||
# 获取异业合作-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e24fdd8dfcfa918e17c30b"}
|
||||
self.different_industries = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.different_industries_list = [item['_widget_1742884829007'] for item in self.different_industries]
|
||||
|
||||
# 获取短信-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e5107198ba1b20d5df3974"}
|
||||
self.groupnotification = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
@staticmethod
|
||||
def download_url_content(url, save_path):
|
||||
"""
|
||||
下载指定 URL 的内容并保存到本地文件。
|
||||
|
||||
:param url: 要下载内容的 URL
|
||||
:param save_path: 保存文件的路径
|
||||
"""
|
||||
try:
|
||||
# 发送 GET 请求以获取内容
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status() # 如果响应状态码不是 200,抛出异常
|
||||
|
||||
# 确保保存目录存在
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
|
||||
# 将内容写入文件
|
||||
with open(save_path, 'wb') as file:
|
||||
for chunk in response.iter_content(chunk_size=8192): # 分块写入,避免占用过多内存
|
||||
if chunk: # 过滤掉空块
|
||||
file.write(chunk)
|
||||
|
||||
print(f"文件已成功保存到 {save_path}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"下载失败: {e}")
|
||||
except Exception as e:
|
||||
print(f"发生错误: {e}")
|
||||
|
||||
@staticmethod
|
||||
def build_index(json_list):
|
||||
index = {}
|
||||
for json_item in json_list:
|
||||
try:
|
||||
key = (json_item['_widget_1734677164861'], json_item['_widget_1734677164862'],
|
||||
json_item['_widget_1734677164863']) # 省市区
|
||||
if '_widget_1734677164871' not in json_item: # 日常回访客服
|
||||
raise KeyError("缺少 '日常回访客服' 键")
|
||||
index[key] = json_item
|
||||
except KeyError as e:
|
||||
print(f"警告:{e},跳过该条记录: {json_item}")
|
||||
continue
|
||||
return index
|
||||
|
||||
@staticmethod
|
||||
def find_customer_service(province_name, city_name, area_name, index):
|
||||
key = (province_name, city_name, area_name)
|
||||
# print(index)
|
||||
if key not in index:
|
||||
return "数据缺失: 未找到对应的日常回访客服"
|
||||
|
||||
return index[key]
|
||||
|
||||
@staticmethod
|
||||
def remove_parentheses(text: str) -> str:
|
||||
# 使用正则表达式匹配并去除括号及其内容
|
||||
# \s* 表示匹配零个或多个空白字符(处理括号前后可能存在的空格)
|
||||
# $ 和 $ 分别表示匹配左括号和右括号
|
||||
# 中间的 .*? 表示非贪婪地匹配任意数量的字符(包括没有字符的情况)
|
||||
cleaned_text = re.sub(r'\s*$.*?$\s*', '', text)
|
||||
# 为了确保同时处理中文括号,再进行一次替换
|
||||
cleaned_text = re.sub(r'\s*(.*?)\s*', '', cleaned_text)
|
||||
return cleaned_text.strip() # 去除两端多余的空白字符
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
return None
|
||||
|
||||
def assign_customer_service(self, province_name, city_name, area_name, index):
|
||||
"""根据省市区派发给日常回访客服"""
|
||||
try:
|
||||
customer_service_info = self.find_customer_service(province_name, city_name, area_name, index)
|
||||
|
||||
# 定义一个辅助函数,用于安全地获取多层字段中的 username
|
||||
def safe_get_username(data, key):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
return data.get(key, {}).get('username', "")
|
||||
return ""
|
||||
except:
|
||||
return ""
|
||||
|
||||
relationship_manager = safe_get_username(customer_service_info, '_widget_1734677164864')
|
||||
customer_service = safe_get_username(customer_service_info, '_widget_1734677164871')
|
||||
technician = safe_get_username(customer_service_info, '_widget_1734677164866')
|
||||
area_manager = safe_get_username(customer_service_info, '_widget_1734677164865')
|
||||
return relationship_manager, customer_service, technician, area_manager
|
||||
except Exception as e:
|
||||
print(f"Error finding customer service: {e}")
|
||||
return "分配失败,请检查", "分配失败,请检查", "分配失败,请检查"
|
||||
|
||||
def calculate_date_one(self, start_offset=0):
|
||||
"""
|
||||
计算从当前日期(或指定偏移量的日期)开始,往前遍历遇到date_list中日期的次数。
|
||||
|
||||
参数:
|
||||
- start_offset: 从当前日期起始的天数偏移量,默认为0(即今天)。负数表示过去,正数表示未来。
|
||||
|
||||
返回:
|
||||
- date_one: 遍历到date_list中日期的次数。
|
||||
"""
|
||||
# 设置起始日期
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=start_offset)
|
||||
|
||||
# 初始化计数器
|
||||
date_one = 1
|
||||
print("当前日期:", now_time.strftime("%Y-%m-%d"))
|
||||
# 检查起始日期是否在date_list中
|
||||
if now_time.strftime("%Y-%m-%d") in self.date_list:
|
||||
date_one = 0
|
||||
print("开始次数:", date_one)
|
||||
else:
|
||||
# 遍历日期
|
||||
for i in range(1, 10):
|
||||
new_date = now_time + datetime.timedelta(days=-i)
|
||||
new_date_str = new_date.strftime("%Y-%m-%d")
|
||||
print("遍历日期:", new_date_str)
|
||||
if new_date_str in self.date_list:
|
||||
date_one += 1
|
||||
print("节假日期:", new_date_str)
|
||||
else:
|
||||
break
|
||||
|
||||
print("遍历次数:", date_one)
|
||||
return date_one
|
||||
|
||||
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)
|
||||
|
||||
# 将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'])
|
||||
|
||||
def replace_values(series):
|
||||
# 使用条件判断来进行替换
|
||||
return series.apply(lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x)
|
||||
|
||||
# 对整个DataFrame的所有列应用替换函数
|
||||
|
||||
# 处理字符串数据并显式指定数据类型
|
||||
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_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")
|
||||
|
||||
# 找到每组中 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])
|
||||
|
||||
# 找到每组中 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')
|
||||
)
|
||||
|
||||
# 将最佳值合并回原数据集
|
||||
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: 过滤条件
|
||||
|
||||
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']]
|
||||
|
||||
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)
|
||||
|
||||
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 = 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]
|
||||
|
||||
# 定义一个函数,用于将数字除以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
|
||||
# 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 = 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}次遍历")
|
||||
import datetime
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=-(i + 1))
|
||||
|
||||
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["主要目的"] = "关怀使用情况,促进增购商机转化,识别潜在风险,及时提报。"
|
||||
|
||||
# 合并三个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)
|
||||
|
||||
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}, # 跟进人是技术专家
|
||||
})
|
||||
|
||||
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"}, # 跟进人是赵柄诚
|
||||
})
|
||||
|
||||
# 输出结果
|
||||
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("_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"]: # 下次是否推荐 功能使用情况表
|
||||
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"]: # 下次是否跟进
|
||||
print(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": "是"}})
|
||||
|
||||
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"
|
||||
] # 智能检测 是否使用
|
||||
|
||||
# 初始化默认值为"否"
|
||||
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:是否拥有
|
||||
else:
|
||||
payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
|
||||
except Exception as e:
|
||||
print(f"私域小程序:Error finding customer service: {e}")
|
||||
|
||||
# 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
|
||||
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:
|
||||
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}")
|
||||
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")
|
||||
|
||||
distribution_date = datetime.datetime.now(datetime.timezone.utc)
|
||||
distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
|
||||
|
||||
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)
|
||||
|
||||
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")
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
print(routine_follow_up_payload)
|
||||
|
||||
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, "续约客户回访")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = RenewServicesRevisit()
|
||||
start.main()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 369 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 154 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 154 KiB |
@@ -0,0 +1,375 @@
|
||||
import pandas as pd
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
from api import API
|
||||
import ast
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil.parser import parse
|
||||
from back_ground_module import CommonModule
|
||||
import numpy as np
|
||||
from config import Config
|
||||
|
||||
common_module = CommonModule()
|
||||
|
||||
|
||||
class CRMDataProcessor:
|
||||
"""泰国CRM数据迁移到BI"""
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化CRM数据处理类
|
||||
"""
|
||||
|
||||
api_key = Config.OVERSEAS_PROJECT_CRM_APP_ID
|
||||
entry_id = Config.OVERSEAS_PROJECT_FOLLOW_UP_PLAN_ENTRY_ID
|
||||
|
||||
self.api_key = api_key
|
||||
self.entry_id = entry_id
|
||||
self.db_config = Config.HS_DB_Config
|
||||
self.api_instance = API()
|
||||
self.connection = None
|
||||
self.cursor = None
|
||||
|
||||
# 字段映射字典
|
||||
self.id_to_name_mapping = {
|
||||
'_widget_0201002000001': '客户编码',
|
||||
'_widget_0201002000002': '门店名称',
|
||||
'_widget_1630862543434': '客户级别',
|
||||
'_widget_1630862543415': 'BD状态',
|
||||
'_widget_1631071964761': '客户来源',
|
||||
'_widget_0201002000005': '所属公海',
|
||||
'_widget_1663742427957': '客户查重',
|
||||
'_widget_1747123933309': '客户BD日期',
|
||||
'_widget_1747661411161': 'Test开始日期',
|
||||
'_widget_1747661411178': 'Test天数',
|
||||
'_widget_1747664949166': 'Test账号状态',
|
||||
'_widget_1747123933310': '客户签约日期',
|
||||
'_widget_1747123933311': '客户付款日期',
|
||||
'_widget_0201002000003': 'BD负责人',
|
||||
'_widget_0201002000006': '销售归属部门',
|
||||
'_widget_0201002000004': 'BD协作人',
|
||||
'_widget_1747133970117': 'BD阻塞原因',
|
||||
'_widget_1747669642443': 'BD阻塞原因分类',
|
||||
'_widget_1747133970121': 'BD阻塞原因详细描述',
|
||||
'_widget_1746675108119': '原系统名称',
|
||||
'_widget_1746675108151': '门店设备',
|
||||
'_widget_1630862543637': '门店类型',
|
||||
'_widget_1746675108121': '门店业务',
|
||||
'_widget_1746675108115': '工位数',
|
||||
'_widget_1747321321284': '员工数',
|
||||
'_widget_1746675108123': '系统操作人员',
|
||||
'_widget_1747123507416': '开户门店ID',
|
||||
'_widget_1737092013289': '公司名称',
|
||||
'_widget_1737092013291': '主店简称',
|
||||
'_widget_1737092013292': '营业执照号',
|
||||
'_widget_1737092013293': '营业执照名称',
|
||||
'_widget_1737097231480': '府',
|
||||
'_widget_1737097231482': '县',
|
||||
'_widget_1737092013299': '地址_省市区',
|
||||
'_widget_1737097782393': '详情地址',
|
||||
'_widget_1737092013314': '营业开始时间',
|
||||
'_widget_1737092013313': '营业结束时间',
|
||||
'_widget_1737092013312': '经度',
|
||||
'_widget_1737092013311': '纬度',
|
||||
'_widget_1737092013310': '负责人名字',
|
||||
'_widget_1737092013308': '负责人手机号',
|
||||
'_widget_1737092013309': '服务接待固话',
|
||||
'_widget_1737092013315': '服务接待名称',
|
||||
'_widget_1737092013316': '服务接待手机号',
|
||||
'_widget_1737092013320': '账号数上限',
|
||||
'_widget_1737092013318': '税号',
|
||||
'_widget_1737092013317': '分支编号',
|
||||
'_widget_1737092013319': '嘉实多内部门店编码',
|
||||
'_widget_1737092013339': '运营顾问_上线负责人',
|
||||
'_widget_1747123933312': '客户上线日期',
|
||||
'_widget_1740460160201': '上线阶段',
|
||||
'_widget_1747133970122': '上线失败原因',
|
||||
'_widget_1631071964934': '上线失败原因描述',
|
||||
'_widget_1749108058561': '门店系统使用情况说明',
|
||||
'_widget_1737092013340': '运营专家',
|
||||
'_widget_1737092013341': '区域经理',
|
||||
'_widget_1663742427909': '客户查重_客户表内该客户数量',
|
||||
'_widget_0201002000007': '领取时间',
|
||||
'_widget_0201002000009': '客户退回原因',
|
||||
'_widget_0201002000008': '最后跟进时间',
|
||||
'plan_recycle_time': "预计回收时间",
|
||||
'_widget_1709110880998': '结算期限',
|
||||
'_widget_1709110881001': '信用额度_元',
|
||||
'_widget_1709110881002': '发票抬头',
|
||||
'_widget_1709110881003': '发票税号',
|
||||
'_widget_1709110881004': '税种',
|
||||
'_widget_1709110881007': '增值税税率_',
|
||||
'_widget_1709110881008': '开户电话',
|
||||
'_widget_1709110881009': '开户银行',
|
||||
'_widget_1709110881016': '银行账户',
|
||||
"_widget_1749204198412": "原系统情况描述",
|
||||
"_widget_1749632087678": "付款金额_泰铢",
|
||||
'creator': '提交人',
|
||||
'createTime': '提交时间',
|
||||
'updateTime': '更新时间'
|
||||
}
|
||||
|
||||
# 需要处理的列
|
||||
self.list_columns_to_process = [
|
||||
'_widget_1746675108123',
|
||||
'_widget_1746675108121',
|
||||
'_widget_1746675108151'
|
||||
]
|
||||
|
||||
self.columns_to_process = [
|
||||
'_widget_0201002000005',
|
||||
'_widget_0201002000003',
|
||||
'_widget_0201002000006',
|
||||
'_widget_0201002000004',
|
||||
'_widget_1737092013339',
|
||||
'_widget_1737092013340',
|
||||
'_widget_1737092013341'
|
||||
]
|
||||
|
||||
self.columns_to_drop = [
|
||||
'_widget_1737097782383',
|
||||
'_widget_1737092013321',
|
||||
'_widget_1737092013300',
|
||||
'_widget_1737092013301',
|
||||
'_widget_1737092013302'
|
||||
]
|
||||
|
||||
self.datetime_columns = [
|
||||
'_widget_1747123933309', # 客户BD日期
|
||||
'_widget_1747123933310', # 客户签约日期
|
||||
'_widget_1747123933311', # 客户付款日期
|
||||
'_widget_0201002000007', # 领取时间
|
||||
'_widget_0201002000008' # 最后跟进时间
|
||||
]
|
||||
|
||||
def connect_db(self):
|
||||
"""连接数据库"""
|
||||
try:
|
||||
self.connection = mysql.connector.connect(
|
||||
host=self.db_config['host'],
|
||||
user=self.db_config['user'],
|
||||
password=self.db_config['password'],
|
||||
database=self.db_config['database']
|
||||
)
|
||||
self.cursor = self.connection.cursor()
|
||||
print(f"成功连接数据库 {self.db_config['database']}")
|
||||
except Error as e:
|
||||
print(f"连接数据库时发生错误: {e}")
|
||||
raise
|
||||
|
||||
def close_db(self):
|
||||
"""关闭数据库连接"""
|
||||
if self.connection and self.connection.is_connected():
|
||||
if self.cursor:
|
||||
self.cursor.close()
|
||||
self.connection.close()
|
||||
print("数据库连接已关闭")
|
||||
|
||||
def fetch_crm_data(self):
|
||||
"""从API获取CRM数据"""
|
||||
payload = {"api_key": self.api_key, "entry_id": self.entry_id}
|
||||
CRM_data_list = self.api_instance.entry_data_list(payload).get("data")
|
||||
CRM_data = pd.DataFrame(CRM_data_list)
|
||||
print("成功从API获取CRM数据")
|
||||
CRM_data.to_csv("CRM.csv")
|
||||
return CRM_data
|
||||
|
||||
def process_data(self, df):
|
||||
"""处理CRM数据"""
|
||||
# 去掉前六列和后两列
|
||||
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"
|
||||
del df['_id']
|
||||
|
||||
# 处理列表格式列
|
||||
for col in self.list_columns_to_process:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(self._join_list_items)
|
||||
|
||||
# 处理字典格式列
|
||||
for col in self.columns_to_process:
|
||||
if col in df.columns:
|
||||
if col == '_widget_0201002000004':
|
||||
df[col] = df[col].apply(self._extract_names_from_list)
|
||||
else:
|
||||
df[col] = df[col].apply(self._extract_name_from_dict)
|
||||
|
||||
# 删除不需要的列
|
||||
for col in self.columns_to_drop:
|
||||
if col in df.columns:
|
||||
df.drop(columns=[col], inplace=True)
|
||||
|
||||
# 处理时间列
|
||||
for col in self.datetime_columns:
|
||||
if col in df.columns:
|
||||
df[col] = df[col].apply(self._add_8_hours)
|
||||
|
||||
# 重命名列
|
||||
df.rename(columns=self.id_to_name_mapping, inplace=True)
|
||||
|
||||
# 只保留映射后的列和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 = df.fillna("") # 先替换NaN和None
|
||||
df = df.replace(r'^\s*$', "", regex=True) # 再替换空字符串
|
||||
|
||||
print("数据处理完成")
|
||||
df.to_csv('DF.csv', index=False)
|
||||
return df
|
||||
|
||||
def _join_list_items(self, cell_value):
|
||||
"""将列表中的内容用逗号分隔"""
|
||||
if pd.api.types.is_list_like(cell_value):
|
||||
return ', '.join(map(str, cell_value))
|
||||
if pd.isna(cell_value) or cell_value == '':
|
||||
return ""
|
||||
try:
|
||||
cell_list = ast.literal_eval(cell_value)
|
||||
return ', '.join(cell_list)
|
||||
except (ValueError, SyntaxError):
|
||||
return str(cell_value)
|
||||
|
||||
def _extract_name_from_dict(self, cell_value):
|
||||
"""提取字典中的'name'值"""
|
||||
if pd.isna(cell_value):
|
||||
return ""
|
||||
if isinstance(cell_value, str):
|
||||
try:
|
||||
cell_dict = ast.literal_eval(cell_value)
|
||||
except (ValueError, SyntaxError):
|
||||
return str(cell_value)
|
||||
else:
|
||||
cell_dict = cell_value
|
||||
return cell_dict.get('name', '')
|
||||
|
||||
def _extract_names_from_list(self, cell_value):
|
||||
"""提取列表中所有字典的'name'值"""
|
||||
if isinstance(cell_value, (pd.Series, np.ndarray)):
|
||||
return cell_value.apply(self._extract_names_from_list)
|
||||
if pd.isna(cell_value).any() if hasattr(cell_value, '__iter__') else pd.isna(cell_value):
|
||||
return ""
|
||||
try:
|
||||
cell_list = ast.literal_eval(cell_value) if isinstance(cell_value, str) else cell_value
|
||||
names = [item.get('name', '') for item in cell_list if isinstance(item, dict)]
|
||||
return ', '.join(names)
|
||||
except (ValueError, SyntaxError, TypeError):
|
||||
return str(cell_value)
|
||||
|
||||
def _add_8_hours(self, dt_str):
|
||||
"""为时间添加8小时"""
|
||||
if pd.isna(dt_str) or dt_str == '':
|
||||
return None
|
||||
try:
|
||||
dt = parse(dt_str)
|
||||
dt += timedelta(hours=8)
|
||||
return dt.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
||||
except Exception as e:
|
||||
print(f"Error processing datetime {dt_str}: {e}")
|
||||
return dt_str
|
||||
|
||||
def clear_table(self, table_name):
|
||||
"""清空数据库表"""
|
||||
try:
|
||||
self.connect_db()
|
||||
self.cursor.execute(f"TRUNCATE TABLE {table_name}")
|
||||
self.connection.commit()
|
||||
print(f"成功清空表 {table_name} 中的所有数据")
|
||||
except Error as e:
|
||||
print(f"清空表时发生错误: {e}")
|
||||
if self.connection and self.connection.is_connected():
|
||||
self.connection.rollback()
|
||||
raise
|
||||
finally:
|
||||
self.close_db()
|
||||
|
||||
def import_data(self, df, table_name):
|
||||
try:
|
||||
self.connect_db()
|
||||
|
||||
# 处理空值 - 将NaN/NaT/空字符串统一转为None
|
||||
df = df.map(lambda x: None if pd.isna(x) or str(x).strip() == '' else x)
|
||||
|
||||
# # 确保所有空值(包括NaN、None、空字符串)转为None
|
||||
df = df.replace([np.nan, None, r'^\s*$'], None, regex=True)
|
||||
|
||||
# 检查表结构是否匹配
|
||||
self.cursor.execute(f"DESCRIBE {table_name}")
|
||||
table_columns = [col[0] for col in self.cursor.fetchall()]
|
||||
|
||||
# 只保留表中存在的列
|
||||
df = df[[col for col in df.columns if col in table_columns]]
|
||||
|
||||
# 生成插入语句
|
||||
columns = ', '.join(df.columns)
|
||||
placeholders = ', '.join(['%s'] * len(df.columns))
|
||||
insert_query = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
|
||||
|
||||
# 批量插入数据
|
||||
records = [tuple(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}")
|
||||
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:
|
||||
# 获取数据
|
||||
raw_data = self.fetch_crm_data()
|
||||
|
||||
# 处理数据
|
||||
processed_data = self.process_data(raw_data)
|
||||
|
||||
# 清空表
|
||||
self.clear_table(table_name)
|
||||
|
||||
# 导入数据
|
||||
self.import_data(processed_data, table_name)
|
||||
|
||||
print("数据处理流程完成")
|
||||
except Exception as e:
|
||||
print(f"数据处理流程出错: {e}")
|
||||
raise
|
||||
|
||||
common_module.send_task_status(task_start_time, "简道云海外项目CRM客户档案迁移BI")
|
||||
|
||||
|
||||
# 使用示例
|
||||
if __name__ == "__main__":
|
||||
# 配置信息
|
||||
|
||||
# 创建处理器实例并运行流程
|
||||
processor = CRMDataProcessor()
|
||||
processor.main()
|
||||
@@ -0,0 +1,113 @@
|
||||
import requests
|
||||
import json
|
||||
import pandas as pd
|
||||
from api import API
|
||||
from config import Config
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
from back_ground_module import CommonModule
|
||||
from datetime import datetime
|
||||
|
||||
# 初始化API实例
|
||||
api_instance = API()
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
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
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.url = "https://api.jiandaoyun.com/api/v5/corp/department/user/list"
|
||||
self.payload1 = {
|
||||
"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
self.delete_payload = {
|
||||
"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
self.update_payload = {
|
||||
"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
|
||||
def get_department_members(self):
|
||||
"""获取部门成员及ID表"""
|
||||
try:
|
||||
payload = json.dumps({
|
||||
"dept_no": 1,
|
||||
"has_child": True
|
||||
})
|
||||
response = requests.request("POST", self.url, headers=self.headers, data=payload)
|
||||
search_department_member = response.json()
|
||||
departments_members = search_department_member.get('users')
|
||||
df1 = pd.DataFrame(departments_members)
|
||||
logger.info("部门成员及ID表已成功获取")
|
||||
return df1
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"获取部门成员及ID表失败:{e}")
|
||||
return None
|
||||
|
||||
def get_existing_id_form(self):
|
||||
"""读取现有的ID表"""
|
||||
try:
|
||||
now_ID_form = api_instance.entry_data_list(self.payload1).get('data')
|
||||
df = pd.DataFrame(now_ID_form)
|
||||
logger.info("现有的ID表已成功读取")
|
||||
return df
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"读取现有的ID表失败:{e}")
|
||||
return None
|
||||
|
||||
def delete_existing_data(self, df):
|
||||
"""批量删除现有数据"""
|
||||
try:
|
||||
all_data = []
|
||||
for index, i in df.iterrows():
|
||||
all_data.append(i["_id"])
|
||||
self.delete_payload["data_ids"] = all_data
|
||||
api_instance.entry_data_batch_delete(self.delete_payload)
|
||||
logger.info("现有数据已成功删除")
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"批量删除现有数据失败:{e}")
|
||||
|
||||
def update_data(self, df1):
|
||||
"""批量写入新数据"""
|
||||
try:
|
||||
all_data1 = []
|
||||
for index, i in df1.iterrows():
|
||||
all_data1.append({
|
||||
"_widget_1734942794144": {"value": i["name"]},
|
||||
"_widget_1734942794145": {"value": i["username"]},
|
||||
})
|
||||
self.update_payload["data_list"] = all_data1
|
||||
api_instance.entry_data_batch_create(self.update_payload)
|
||||
logger.info("新数据已成功写入")
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"批量写入新数据失败:{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表更新")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
daily_task = update_ID_form()
|
||||
daily_task.main()
|
||||
@@ -0,0 +1,228 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pandas as pd
|
||||
import datetime
|
||||
from config import Config
|
||||
from api import API
|
||||
from back_ground_module import CommonModule
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
|
||||
|
||||
class UpdateNGVData:
|
||||
"""NGV数据每日新增"""
|
||||
def __init__(self):
|
||||
self.staff_id_list = None
|
||||
self.field_mapping = {}
|
||||
self.fields()
|
||||
|
||||
def load_all_data(self):
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
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)
|
||||
|
||||
# 找出在 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'])]
|
||||
|
||||
# 创建一个新的 DataFrame 保存这些唯一的 data_id 及其对应的数据
|
||||
new_df = data_NGV_j[data_NGV_j['org_code'].isin(unique_data_ids['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'] == '一般']
|
||||
|
||||
# 日期字段转换为日期格式
|
||||
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)
|
||||
|
||||
# 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')
|
||||
)
|
||||
|
||||
# 人员字段转换为人员字段
|
||||
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
|
||||
|
||||
# filtered_df.to_csv(r"D:\Idea Project\SaaS_V1.3\back_ground_module\output\NGV.csv")
|
||||
|
||||
# 生成包含所有行转换后的字典列表
|
||||
# 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()] # 增量数据
|
||||
|
||||
#
|
||||
data = {'api_key': Config.SaaS_Tasks_APP_ID, 'entry_id': Config.NGV_TASKS_ENTRY_ID, "data_list": all_data}
|
||||
|
||||
result = api_instance.entry_data_batch_create(data)
|
||||
# result_str = str(result)
|
||||
# print(result_str[:500])
|
||||
|
||||
# 保存到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)
|
||||
|
||||
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, "NGV新增数据")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = dict(date_id='_widget_1734062123065', date_fmt='_widget_1734062123066',
|
||||
id_own_group='_widget_1734062123067', group_name='_widget_1734062123068',
|
||||
id_own_org='_widget_1734062123069', org_name='_widget_1734062123070',
|
||||
org_code='_widget_1734062123071', group_grade='_widget_1734062123072',
|
||||
org_type='_widget_1734062123073', org_status='_widget_1734062123074',
|
||||
saas_version='_widget_1734062123075', is_wechat='_widget_1734062123076',
|
||||
is_mini_app='_widget_1734062123077', is_wx_shop='_widget_1734062123078',
|
||||
is_camera_service='_widget_1734062123079',
|
||||
is_maintenance_service='_widget_1734062123080',
|
||||
saas_create_time='_widget_1734062123081', expiry_time='_widget_1734062123082',
|
||||
saas_use_days='_widget_1734062123083', saas_use_year='_widget_1734062123084',
|
||||
is_main_org='_widget_1734062123085', license_code='_widget_1734062123086',
|
||||
license_name='_widget_1734062123087', org_crm_id='_widget_1734062123088',
|
||||
province_id='_widget_1734062123089', province_name='_widget_1734062123090',
|
||||
city_id='_widget_1734062123091', city_name='_widget_1734062123092',
|
||||
area_id='_widget_1734062123093', area_name='_widget_1734062123094',
|
||||
region_name='_widget_1734062123095', region_short_name='_widget_1734062123096',
|
||||
branch_name='_widget_1734062123097', carzone_store_id='_widget_1734062123098',
|
||||
carzone_store_name='_widget_1734062123099',
|
||||
customer_carzone_id='_widget_1734062123100', salesmen='_widget_1734062123101',
|
||||
area_manager='_widget_1734062123102', service_salesmen='_widget_1734062123103',
|
||||
impl_principal='_widget_1734062123104',
|
||||
service_impl_principal='_widget_1734062123105',
|
||||
active_user_count='_widget_1734062123106', active_user_type='_widget_1734062123107',
|
||||
limit_user_count='_widget_1734062123108', limit_user_type='_widget_1734062123109',
|
||||
is_n='_widget_1734062123110', is_g='_widget_1734062123111',
|
||||
is_v='_widget_1734062123112', is_visited='_widget_1734062123113',
|
||||
is_active='_widget_1734062123114', active_status_fmt='_widget_1734062123115',
|
||||
bill_count_last_30_day='_widget_1734062123116',
|
||||
bill_day_count_last_30_day='_widget_1734062123117',
|
||||
bill_day_count_this_month='_widget_1734062123118',
|
||||
bill_count_last_7_day='_widget_1734062123119',
|
||||
bill_day_count_last_7_day='_widget_1734062123120', pv_count='_widget_1734062123121',
|
||||
uv_count='_widget_1734062123122', bill_count_1d='_widget_1734062123123',
|
||||
bill_count_2d='_widget_1734062123124', bill_count_3d='_widget_1734062123125',
|
||||
bill_count_4d='_widget_1734062123126', bill_count_5d='_widget_1734062123127',
|
||||
bill_count_6d='_widget_1734062123128', bill_count_7d='_widget_1734062123129',
|
||||
bill_count_8d='_widget_1734062123130', bill_count_9d='_widget_1734062123131',
|
||||
bill_count_10d='_widget_1734062123132', bill_count_11d='_widget_1734062123133',
|
||||
bill_count_12d='_widget_1734062123134', bill_count_13d='_widget_1734062123135',
|
||||
bill_count_14d='_widget_1734062123136', bill_count_15d='_widget_1734062123137',
|
||||
bill_count_16d='_widget_1734062123138', bill_count_17d='_widget_1734062123139',
|
||||
bill_count_18d='_widget_1734062123140', bill_count_19d='_widget_1734062123141',
|
||||
bill_count_20d='_widget_1734062123142', bill_count_21d='_widget_1734062123143',
|
||||
bill_count_22d='_widget_1734062123144', bill_count_23d='_widget_1734062123145',
|
||||
bill_count_24d='_widget_1734062123146', bill_count_25d='_widget_1734062123147',
|
||||
bill_count_26d='_widget_1734062123148', bill_count_27d='_widget_1734062123149',
|
||||
bill_count_28d='_widget_1734062123150', bill_count_29d='_widget_1734062123151',
|
||||
bill_count_30d='_widget_1734062123152', bill_count_31d='_widget_1734062123153',
|
||||
etl_time='_widget_1734062123154',
|
||||
maintain_bill_count_last_30_day='_widget_1734062123155',
|
||||
washing_bill_count_last_30_day='_widget_1734062123156',
|
||||
maintain_bill_day_count_last_30_day='_widget_1734062123157',
|
||||
washing_bill_day_count_last_30_day='_widget_1734062123158',
|
||||
retail_bill_count_last_30_day='_widget_1734062123159',
|
||||
retail_bill_day_count_last_30_day='_widget_1734062123160',
|
||||
purchase_bill_count_last_30_day='_widget_1734062123161',
|
||||
purchase_bill_day_count_last_30_day='_widget_1734062123162',
|
||||
card_bill_count_last_30_day='_widget_1734062123163',
|
||||
card_bill_day_count_last_30_day='_widget_1734062123164',
|
||||
gd_sales_bill_count_last_30_day='_widget_1734062123165',
|
||||
gd_sales_bill_day_count_last_30_day='_widget_1734062123166',
|
||||
g_change_flag='_widget_1734062123167', saas_package='_widget_1734062123168',
|
||||
manage_model='_widget_1734062123169', contacts='_widget_1734062123170',
|
||||
contact_number='_widget_1734062123171', contact_mobile='_widget_1734062123172',
|
||||
g_month_count='_widget_1734062123173', g_month_percentage='_widget_1734062123174',
|
||||
is_install_service='_widget_1734062123175',
|
||||
install_create_time='_widget_1734062123176', last_end_date='_widget_1734062123177',
|
||||
renew_date='_widget_1734062123178', is_chain_owner='_widget_1734062123179',
|
||||
group_org_count='_widget_1734062123180',
|
||||
recent_bill_warning_days='_widget_1734062123181',
|
||||
g_change_flag_d='_widget_1734062123182', g_lost_warning_days='_widget_1734062123183',
|
||||
saas_edition_fmt='_widget_1734062123184', g_flag_1m='_widget_1734062123185',
|
||||
g_flag_2m='_widget_1734062123186', g_flag_3m='_widget_1734062123187',
|
||||
g_flag_4m='_widget_1734062123188', g_flag_5m='_widget_1734062123189',
|
||||
g_flag_6m='_widget_1734062123190', g_flag_day_count='_widget_1734062123191',
|
||||
add_org_flag='_widget_1734062123192', pt='_widget_1734062123193',
|
||||
org_size='_widget_1734062123194', qualification_type_fmt='_widget_1734062123195',
|
||||
business_scope_fmt='_widget_1734062123196', store_type_fmt='_widget_1734062123197',
|
||||
area='_widget_1734062123198', station_number='_widget_1734062123199',
|
||||
header_type_fmt='_widget_1734062123200', org_stage='_widget_1734062123201',
|
||||
g_count_this_month='_widget_1734062123202',
|
||||
saas_customer_type='_widget_1734062123203', technician='_widget_1734062123204',
|
||||
tmall_maintain_service_status_desc='_widget_1734062123205',
|
||||
date_fmt_date='_widget_1749000071375',
|
||||
area_manager_staff_id='_widget_1748496855779',
|
||||
service_impl_principal_staff_id="_widget_1748496855780",
|
||||
service_salesmen_staff_id="_widget_1748496855778",
|
||||
technician_staff_id="_widget_1751877712235",
|
||||
saas_create_time_date="_widget_1749000071377",
|
||||
expiry_time_date="_widget_1749000071382",
|
||||
install_create_time_date="_widget_1749000071384",
|
||||
last_end_date_date="_widget_1749000071389", renew_date_date="_widget_1749000071391")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = UpdateNGVData()
|
||||
start.main()
|
||||
@@ -0,0 +1,359 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pandas as pd
|
||||
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
|
||||
import concurrent.futures
|
||||
|
||||
# 获取已经配置好的常规日志记录器
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
|
||||
|
||||
class UpdateAllNGVDataDaily:
|
||||
"""NGV数据每日更新"""
|
||||
|
||||
def __init__(self):
|
||||
self.field_mapping = {}
|
||||
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)
|
||||
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 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'] == '一般']
|
||||
|
||||
# 去除不需要的列
|
||||
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)
|
||||
|
||||
# 过滤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_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
|
||||
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的内容
|
||||
comparison_column = 'match_status'
|
||||
|
||||
# 创建一个布尔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)
|
||||
# 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)
|
||||
|
||||
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中的行
|
||||
# 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')
|
||||
|
||||
# print(f"\nCSV文件已保存到目录: {output_dir}")
|
||||
|
||||
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)
|
||||
|
||||
# 如果简道云存在,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": "已删除"}}
|
||||
}
|
||||
|
||||
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'] == '不一致']
|
||||
|
||||
# 日期字段转换为日期格式
|
||||
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')
|
||||
)
|
||||
|
||||
# 人员字段转换为人员字段
|
||||
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
|
||||
|
||||
# 并发请求
|
||||
futures = []
|
||||
all_data = []
|
||||
|
||||
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}
|
||||
|
||||
# 单独处理 _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
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
# all_data.append(data_dict)
|
||||
|
||||
# 收集所有结果
|
||||
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更新数据")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为指定格式的字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
|
||||
return result
|
||||
|
||||
def fields(self):
|
||||
self.field_mapping = dict(date_id='_widget_1734062123065', date_fmt='_widget_1734062123066',
|
||||
id_own_group='_widget_1734062123067', group_name='_widget_1734062123068',
|
||||
id_own_org='_widget_1734062123069', org_name='_widget_1734062123070',
|
||||
org_code='_widget_1734062123071', group_grade='_widget_1734062123072',
|
||||
org_type='_widget_1734062123073', org_status='_widget_1734062123074',
|
||||
saas_version='_widget_1734062123075', is_wechat='_widget_1734062123076',
|
||||
is_mini_app='_widget_1734062123077', is_wx_shop='_widget_1734062123078',
|
||||
is_camera_service='_widget_1734062123079',
|
||||
is_maintenance_service='_widget_1734062123080',
|
||||
saas_create_time='_widget_1734062123081', expiry_time='_widget_1734062123082',
|
||||
saas_use_days='_widget_1734062123083', saas_use_year='_widget_1734062123084',
|
||||
is_main_org='_widget_1734062123085', license_code='_widget_1734062123086',
|
||||
license_name='_widget_1734062123087', org_crm_id='_widget_1734062123088',
|
||||
province_id='_widget_1734062123089', province_name='_widget_1734062123090',
|
||||
city_id='_widget_1734062123091', city_name='_widget_1734062123092',
|
||||
area_id='_widget_1734062123093', area_name='_widget_1734062123094',
|
||||
region_name='_widget_1734062123095', region_short_name='_widget_1734062123096',
|
||||
branch_name='_widget_1734062123097', carzone_store_id='_widget_1734062123098',
|
||||
carzone_store_name='_widget_1734062123099',
|
||||
customer_carzone_id='_widget_1734062123100', salesmen='_widget_1734062123101',
|
||||
area_manager='_widget_1734062123102', service_salesmen='_widget_1734062123103',
|
||||
impl_principal='_widget_1734062123104',
|
||||
service_impl_principal='_widget_1734062123105',
|
||||
active_user_count='_widget_1734062123106', active_user_type='_widget_1734062123107',
|
||||
limit_user_count='_widget_1734062123108', limit_user_type='_widget_1734062123109',
|
||||
is_n='_widget_1734062123110', is_g='_widget_1734062123111',
|
||||
is_v='_widget_1734062123112', is_visited='_widget_1734062123113',
|
||||
is_active='_widget_1734062123114', active_status_fmt='_widget_1734062123115',
|
||||
bill_count_last_30_day='_widget_1734062123116',
|
||||
bill_day_count_last_30_day='_widget_1734062123117',
|
||||
bill_day_count_this_month='_widget_1734062123118',
|
||||
bill_count_last_7_day='_widget_1734062123119',
|
||||
bill_day_count_last_7_day='_widget_1734062123120', pv_count='_widget_1734062123121',
|
||||
uv_count='_widget_1734062123122', bill_count_1d='_widget_1734062123123',
|
||||
bill_count_2d='_widget_1734062123124', bill_count_3d='_widget_1734062123125',
|
||||
bill_count_4d='_widget_1734062123126', bill_count_5d='_widget_1734062123127',
|
||||
bill_count_6d='_widget_1734062123128', bill_count_7d='_widget_1734062123129',
|
||||
bill_count_8d='_widget_1734062123130', bill_count_9d='_widget_1734062123131',
|
||||
bill_count_10d='_widget_1734062123132', bill_count_11d='_widget_1734062123133',
|
||||
bill_count_12d='_widget_1734062123134', bill_count_13d='_widget_1734062123135',
|
||||
bill_count_14d='_widget_1734062123136', bill_count_15d='_widget_1734062123137',
|
||||
bill_count_16d='_widget_1734062123138', bill_count_17d='_widget_1734062123139',
|
||||
bill_count_18d='_widget_1734062123140', bill_count_19d='_widget_1734062123141',
|
||||
bill_count_20d='_widget_1734062123142', bill_count_21d='_widget_1734062123143',
|
||||
bill_count_22d='_widget_1734062123144', bill_count_23d='_widget_1734062123145',
|
||||
bill_count_24d='_widget_1734062123146', bill_count_25d='_widget_1734062123147',
|
||||
bill_count_26d='_widget_1734062123148', bill_count_27d='_widget_1734062123149',
|
||||
bill_count_28d='_widget_1734062123150', bill_count_29d='_widget_1734062123151',
|
||||
bill_count_30d='_widget_1734062123152', bill_count_31d='_widget_1734062123153',
|
||||
etl_time='_widget_1734062123154',
|
||||
maintain_bill_count_last_30_day='_widget_1734062123155',
|
||||
washing_bill_count_last_30_day='_widget_1734062123156',
|
||||
maintain_bill_day_count_last_30_day='_widget_1734062123157',
|
||||
washing_bill_day_count_last_30_day='_widget_1734062123158',
|
||||
retail_bill_count_last_30_day='_widget_1734062123159',
|
||||
retail_bill_day_count_last_30_day='_widget_1734062123160',
|
||||
purchase_bill_count_last_30_day='_widget_1734062123161',
|
||||
purchase_bill_day_count_last_30_day='_widget_1734062123162',
|
||||
card_bill_count_last_30_day='_widget_1734062123163',
|
||||
card_bill_day_count_last_30_day='_widget_1734062123164',
|
||||
gd_sales_bill_count_last_30_day='_widget_1734062123165',
|
||||
gd_sales_bill_day_count_last_30_day='_widget_1734062123166',
|
||||
g_change_flag='_widget_1734062123167', saas_package='_widget_1734062123168',
|
||||
manage_model='_widget_1734062123169', contacts='_widget_1734062123170',
|
||||
contact_number='_widget_1734062123171', contact_mobile='_widget_1734062123172',
|
||||
g_month_count='_widget_1734062123173', g_month_percentage='_widget_1734062123174',
|
||||
is_install_service='_widget_1734062123175',
|
||||
install_create_time='_widget_1734062123176', last_end_date='_widget_1734062123177',
|
||||
renew_date='_widget_1734062123178', is_chain_owner='_widget_1734062123179',
|
||||
group_org_count='_widget_1734062123180',
|
||||
recent_bill_warning_days='_widget_1734062123181',
|
||||
g_change_flag_d='_widget_1734062123182', g_lost_warning_days='_widget_1734062123183',
|
||||
saas_edition_fmt='_widget_1734062123184', g_flag_1m='_widget_1734062123185',
|
||||
g_flag_2m='_widget_1734062123186', g_flag_3m='_widget_1734062123187',
|
||||
g_flag_4m='_widget_1734062123188', g_flag_5m='_widget_1734062123189',
|
||||
g_flag_6m='_widget_1734062123190', g_flag_day_count='_widget_1734062123191',
|
||||
add_org_flag='_widget_1734062123192', pt='_widget_1734062123193',
|
||||
org_size='_widget_1734062123194', qualification_type_fmt='_widget_1734062123195',
|
||||
business_scope_fmt='_widget_1734062123196', store_type_fmt='_widget_1734062123197',
|
||||
area='_widget_1734062123198', station_number='_widget_1734062123199',
|
||||
header_type_fmt='_widget_1734062123200', org_stage='_widget_1734062123201',
|
||||
g_count_this_month='_widget_1734062123202',
|
||||
saas_customer_type='_widget_1734062123203', technician='_widget_1734062123204',
|
||||
tmall_maintain_service_status_desc='_widget_1734062123205',
|
||||
date_fmt_date='_widget_1749000071375',
|
||||
area_manager_staff_id='_widget_1748496855779',
|
||||
service_impl_principal_staff_id="_widget_1748496855780",
|
||||
service_salesmen_staff_id="_widget_1748496855778",
|
||||
technician_staff_id="_widget_1751877712235",
|
||||
saas_create_time_date="_widget_1749000071377",
|
||||
expiry_time_date="_widget_1749000071382",
|
||||
install_create_time_date="_widget_1749000071384",
|
||||
last_end_date_date="_widget_1749000071389", renew_date_date="_widget_1749000071391")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = UpdateAllNGVDataDaily()
|
||||
start.main()
|
||||
@@ -0,0 +1,224 @@
|
||||
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 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
|
||||
import re
|
||||
import json
|
||||
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
# 初始化 API 实例和 Token
|
||||
yd_api_instance = YDAPI()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
TOKEN = yd_api_instance.generateToken()
|
||||
|
||||
# 配置常量
|
||||
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:
|
||||
"""分母报备调整"""
|
||||
|
||||
def __init__(self):
|
||||
self.structures = None
|
||||
self.denominator_data_list = None
|
||||
|
||||
self.field_map = {
|
||||
"门店编码": "textField_pl5p5a3",
|
||||
"门店名称": "textField_fcl5xg6",
|
||||
"公司名称": "textField_bdlfhio",
|
||||
"大区": "textField_urgu3fr",
|
||||
"小区": "textField_dro2c5y",
|
||||
"战区": "textField_e3pkxp1",
|
||||
"技术专家": "employeeField_mca5shp0",
|
||||
"区域客成": "employeeField_mca5shp1",
|
||||
"运营负责人": "textField_j9uxos9",
|
||||
"SaaS版本": "textField_0hbyovw",
|
||||
"开户日期": "dateField_dnj8hop",
|
||||
"开始时间": "dateField_ppr0d3a",
|
||||
"结束时间": "dateField_jvsr6ef",
|
||||
"原分母金额": "numberField_l4bcg80",
|
||||
"调整后金额": "numberField_9bjyfzj",
|
||||
"分母调整理由": "textField_niczt1b",
|
||||
"对应订单编码": "textField_2ubszzt",
|
||||
"转养车后门店编码": "textField_q14ebff",
|
||||
"总部调整备注": "textareaField_lfrnbtbu",
|
||||
"总部调整结果": "selectField_lfqwg05y",
|
||||
"总部核对结果": "selectField_lfqwg05x",
|
||||
"是否上传衡石": "selectField_mca5shoz",
|
||||
"是否计入应续约数": "selectField_mdnwwvyo"
|
||||
}
|
||||
|
||||
def get_yida_data(self):
|
||||
# 获取分母报备数据
|
||||
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'$[^)]*$')
|
||||
for a in range(1, PAGES_two + 1):
|
||||
denominator_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=a, n=100,
|
||||
appType=appType, systemToken=systemToken)
|
||||
for item in denominator_data.get("data", []):
|
||||
form_data = item.get("formData", {})
|
||||
# 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:
|
||||
# 取第一个元素
|
||||
raw_value = form_data[field_key][0]
|
||||
# 去除括号及其中的内容
|
||||
cleaned_value = parentheses_pattern.sub('', raw_value).strip()
|
||||
# 更新 formData 中的值
|
||||
form_data[field_key] = cleaned_value
|
||||
|
||||
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:
|
||||
transformed_data[display_name] = value
|
||||
break
|
||||
# print(transformed_data.get("是否上传衡石"))
|
||||
# if transformed_data.get("是否上传衡石") == "否" or transformed_data.get("是否上传衡石") is None:
|
||||
# continue
|
||||
self.denominator_data_list.append(transformed_data)
|
||||
|
||||
|
||||
|
||||
def execute_sql(self, sql, params=None, fetch=False, many=False):
|
||||
"""执行SQL语句"""
|
||||
conn = None
|
||||
try:
|
||||
conn = mysql.connector.connect(**DB_CONFIG)
|
||||
cursor = conn.cursor()
|
||||
if many:
|
||||
cursor.executemany(sql, params)
|
||||
else:
|
||||
cursor.execute(sql, params or ())
|
||||
conn.commit()
|
||||
return cursor.fetchall() if fetch else cursor
|
||||
except Error as e:
|
||||
print(f"执行失败: {sql}\n错误: {e}")
|
||||
if conn: conn.rollback()
|
||||
return None
|
||||
finally:
|
||||
if conn and conn.is_connected():
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
def write_to_bi(self, df):
|
||||
# 数据库连接信息
|
||||
table_name = "f6_denominator_adjustment" # 替换为你的实际表名
|
||||
|
||||
# 建立数据库连接
|
||||
connection = mysql.connector.connect(
|
||||
host=DB_CONFIG["host"],
|
||||
user=DB_CONFIG["user"],
|
||||
password=DB_CONFIG["password"],
|
||||
database=DB_CONFIG["database"]
|
||||
)
|
||||
cursor = connection.cursor()
|
||||
|
||||
try:
|
||||
# 查询表列名
|
||||
cursor.execute(f"SHOW COLUMNS FROM {table_name}")
|
||||
columns_info = cursor.fetchall()
|
||||
db_columns = [col[0] for col in columns_info] # 提取列名
|
||||
df = df.replace([None, np.nan, pd.NA, 'nan', 'NaN', 'NAN', ''], None)
|
||||
# 保留 DataFrame 中与数据库列名匹配的列
|
||||
filtered_df = df[df.columns.intersection(db_columns)]
|
||||
|
||||
|
||||
# 如果没有匹配的列,直接返回
|
||||
if filtered_df.empty:
|
||||
print("DataFrame 中没有与数据库表结构匹配的列。")
|
||||
return
|
||||
|
||||
# 筛选列之后,插入前处理 dict 类型
|
||||
filtered_df = filtered_df.copy()
|
||||
for col in filtered_df.columns:
|
||||
if filtered_df[col].apply(lambda x: isinstance(x, (dict, list)) if x is not None else False).any():
|
||||
filtered_df.loc[:, col] = filtered_df[col].apply(
|
||||
lambda x: json.dumps(x, ensure_ascii=False) if x is not None else x
|
||||
)
|
||||
|
||||
|
||||
# 构建插入语句
|
||||
placeholders = ', '.join(['%s'] * len(filtered_df.columns))
|
||||
# 使用反引号避免特殊列明
|
||||
columns = ', '.join([f"`{col}`" for col in filtered_df.columns])
|
||||
insert_sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
|
||||
|
||||
# 将 DataFrame 写入数据库
|
||||
for _, row in filtered_df.iterrows():
|
||||
cursor.execute(insert_sql, tuple(row))
|
||||
|
||||
|
||||
connection.commit()
|
||||
print(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
|
||||
|
||||
except Exception as e:
|
||||
print("写入数据库时发生错误:", e)
|
||||
connection.rollback()
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
def clear_table(self):
|
||||
"""清空表数据"""
|
||||
if self.execute_sql("TRUNCATE TABLE f6_denominator_adjustment"):
|
||||
print("✅ 成功清空表数据")
|
||||
|
||||
def main(self):
|
||||
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
# step1:获取宜搭数据
|
||||
self.get_yida_data()
|
||||
|
||||
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')
|
||||
|
||||
|
||||
# step2:清空BI数据表
|
||||
self.clear_table()
|
||||
|
||||
# # step3:写入BI数据库
|
||||
self.write_to_bi(df)
|
||||
|
||||
common_module.send_task_status(task_start_time, "分母报备调整")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
denominator_reporting_adjustment = DenominatorReportingAdjustment()
|
||||
denominator_reporting_adjustment.main()
|
||||
@@ -0,0 +1,323 @@
|
||||
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
|
||||
from datetime import datetime
|
||||
from config import Config
|
||||
from api import API
|
||||
from back_ground_module import CommonModule
|
||||
import pandas as pd
|
||||
import pymysql
|
||||
from pymysql import Error
|
||||
|
||||
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.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')
|
||||
|
||||
# 初始化字段映射
|
||||
self.field_mapping = {
|
||||
"指标归属日期": "_widget_1742174728275",
|
||||
"公司ID": "_widget_1742091963874",
|
||||
"公司名称": "_widget_1742091963875",
|
||||
"门店ID": "_widget_1742091963876",
|
||||
"门店名称": "_widget_1742091963877",
|
||||
"门店简称": "_widget_1742091963878",
|
||||
"门店创建时间": "_widget_1742091963879",
|
||||
"指标类型": "_widget_1742091963880",
|
||||
"指标值": "_widget_1742091963882",
|
||||
"指标子类型": "_widget_1742091963881",
|
||||
"指标值": "_widget_1742091963882"
|
||||
}
|
||||
|
||||
def connect_email_by_pop3(self):
|
||||
try:
|
||||
# 连接到POP服务器
|
||||
email_server = poplib.POP3_SSL(
|
||||
host=self.pop_server_host,
|
||||
port=self.pop_server_port,
|
||||
timeout=10
|
||||
)
|
||||
print("POP服务器连接成功,开始用户邮箱验证")
|
||||
except Exception as e:
|
||||
print(f"POP服务器连接失败。错误: {str(e)}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
# 验证用户邮箱
|
||||
email_server.user(self.user_email_address)
|
||||
print("用户邮箱验证成功,开始授权码验证")
|
||||
except Exception as e:
|
||||
print(f"用户邮箱验证失败。错误: {str(e)}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
# 验证密码/授权码
|
||||
email_server.pass_(self.user_password)
|
||||
print("授权码验证成功,开始处理邮件")
|
||||
except Exception as e:
|
||||
print(f"授权码验证失败。错误: {str(e)}")
|
||||
exit(1)
|
||||
|
||||
# 处理邮件
|
||||
self.parse_email_server(email_server)
|
||||
|
||||
def parse_email_server(self, email_server):
|
||||
# 获取所有邮件列表
|
||||
resp, mails, octets = email_server.list()
|
||||
index = len(mails)
|
||||
|
||||
# 获取今天的零点时间戳
|
||||
now = datetime.now()
|
||||
today_start = datetime(now.year, now.month, now.day) # 当天零点
|
||||
today_start_timestamp = int(today_start.timestamp()) # 转换为时间戳
|
||||
|
||||
# 按逆序处理邮件(最新的先处理)
|
||||
for i in range(index, 0, -1):
|
||||
|
||||
# print(f"正在处理邮件 {i},{index}")
|
||||
|
||||
try:
|
||||
# 获取邮件内容
|
||||
resp, lines, octets = email_server.retr(i)
|
||||
msg_content = b'\r\n'.join(lines).decode('utf-8', errors='ignore') # 避免解码错误
|
||||
msg = Parser().parsestr(msg_content)
|
||||
|
||||
# 处理邮件时间
|
||||
mail_datetime = self.parse_mail_time(msg.get("date"))
|
||||
if not mail_datetime: # 如果邮件时间解析失败,跳过
|
||||
# logging.warning(f"Failed to parse date for email {i}. Skipping...")
|
||||
continue
|
||||
|
||||
# 将邮件时间转换为时间戳
|
||||
mail_timestamp = int(mail_datetime.timestamp())
|
||||
|
||||
# 如果邮件不是今天的,跳过
|
||||
if mail_timestamp < today_start_timestamp:
|
||||
# logging.info(f"Skipping email {i} as it is not from today.")
|
||||
# continue
|
||||
break
|
||||
|
||||
# 打印邮件接收时间
|
||||
mail_time_str = datetime.strftime(mail_datetime, '%Y-%m-%d %H:%M:%S')
|
||||
print(f"邮件接收时间: {mail_time_str}")
|
||||
|
||||
# 处理邮件内容
|
||||
self.parser_content(msg, 0)
|
||||
|
||||
except Exception as e:
|
||||
# logging.error(f"Error processing email {i}: {e}")
|
||||
print(f"Error processing email {i}: {e}")
|
||||
continue
|
||||
|
||||
# 退出服务器
|
||||
email_server.quit()
|
||||
|
||||
def parser_content(self, msg, indent):
|
||||
print("邮件处理")
|
||||
if indent == 0:
|
||||
self.parser_email_header(msg)
|
||||
|
||||
# 解析发件人信息
|
||||
hdr, addr = parseaddr(msg['From'])
|
||||
name, charset = decode_header(hdr)[0]
|
||||
if charset:
|
||||
name = name.decode(charset)
|
||||
print(f'发件人姓名: {name}, 发件人邮箱: {addr}')
|
||||
|
||||
if name == self.send_name:
|
||||
# 下载附件
|
||||
for part in msg.walk():
|
||||
file_name = part.get_filename()
|
||||
if file_name is None:
|
||||
continue
|
||||
|
||||
filename = self.decode_str(file_name)
|
||||
data = part.get_payload(decode=True)
|
||||
try:
|
||||
with open(self.write_path, 'wb') as att_file:
|
||||
att_file.write(data)
|
||||
print(f"附件保存成功: {self.write_path}+{filename}")
|
||||
except Exception as e:
|
||||
print(f"附件保存失败: {str(e)}")
|
||||
|
||||
if msg.is_multipart():
|
||||
parts = msg.get_payload()
|
||||
for part in parts:
|
||||
self.parser_content(part, indent + 1)
|
||||
else:
|
||||
# 解析邮件正文
|
||||
content_type = msg.get_content_type()
|
||||
if content_type in ['text/plain', 'text/html']:
|
||||
content = msg.get_payload(decode=True)
|
||||
charset = self.guess_charset(msg)
|
||||
if charset:
|
||||
content = content.decode(charset)
|
||||
print(f"{' ' * indent}邮件内容: {content}")
|
||||
|
||||
def parser_email_header(self, msg):
|
||||
# 解析邮件主题
|
||||
subject = msg['Subject']
|
||||
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]
|
||||
if charset:
|
||||
name = name.decode(charset)
|
||||
print(f'发件人姓名: {name}, 发件人邮箱: {addr}')
|
||||
|
||||
# 解析收件人信息
|
||||
hdr, addr = parseaddr(msg['To'])
|
||||
name, charset = decode_header(hdr)[0]
|
||||
if charset:
|
||||
name = name.decode(charset)
|
||||
print(f'收件人姓名: {name}, 收件人邮箱: {addr}')
|
||||
|
||||
@staticmethod
|
||||
def decode_str(s):
|
||||
value, charset = decode_header(s)[0]
|
||||
if charset:
|
||||
value = value.decode(charset)
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def guess_charset(msg):
|
||||
charset = msg.get_charset()
|
||||
if charset is None:
|
||||
content_type = msg.get('Content-Type', '').lower()
|
||||
for item in content_type.split(';'):
|
||||
item = item.strip()
|
||||
if item.startswith('charset'):
|
||||
charset = item.split('=')[1]
|
||||
break
|
||||
return charset
|
||||
|
||||
@staticmethod
|
||||
def parse_mail_time(mail_datetime):
|
||||
GMT_FORMAT = "%a, %d %b %Y %H:%M:%S"
|
||||
GMT_FORMAT2 = "%d %b %Y %H:%M:%S"
|
||||
index = mail_datetime.find(' +0')
|
||||
if index > 0:
|
||||
mail_datetime = mail_datetime[:index] # 移除时区信息
|
||||
formats = [GMT_FORMAT, GMT_FORMAT2]
|
||||
for ft in formats:
|
||||
try:
|
||||
mail_datetime = datetime.strptime(mail_datetime, ft)
|
||||
return mail_datetime
|
||||
except:
|
||||
pass
|
||||
raise Exception("邮件时间格式解析错误")
|
||||
|
||||
@staticmethod
|
||||
def row_to_dict(row, field_mapping):
|
||||
"""将一行数据转换为格式化字典"""
|
||||
result = {}
|
||||
for col_name, widget_id in field_mapping.items():
|
||||
if col_name in row:
|
||||
value = row[col_name]
|
||||
clean_value = None if pd.isna(value) else value
|
||||
result[widget_id] = {"value": clean_value}
|
||||
return result
|
||||
|
||||
def update_email(self):
|
||||
# try:
|
||||
print(self.write_path)
|
||||
email_df = pd.read_excel(self.write_path, sheet_name="Sheet0")
|
||||
|
||||
print(email_df.head())
|
||||
email_df['公司ID'] = email_df['公司ID'].astype(str)
|
||||
email_df['门店ID'] = email_df['门店ID'].astype(str)
|
||||
email_df['指标归属日期'] = pd.to_datetime(email_df['指标归属日期'], format="%Y/%m/%d").dt.strftime("%Y-%m-%d")
|
||||
email_df["门店创建时间"] = pd.to_datetime(email_df['门店创建时间'], format="%Y-%m-%d %H:%M:%S")
|
||||
new_email_df = email_df.copy() # 拷贝传参
|
||||
for index, row in email_df.iterrows():
|
||||
email_df.loc[index, '指标归属日期'] = common_module.time_to_UTC(row['指标归属日期'])
|
||||
email_df.loc[index, '门店创建时间'] = common_module.time_to_UTC(row['门店创建时间'])
|
||||
|
||||
email_data = [self.row_to_dict(row, self.field_mapping) for index, row in email_df.iterrows()]
|
||||
new_email_data = {'api_key': "673457d6837e60a418e0e56b",
|
||||
'entry_id': "67d636bb6212b7619a7a4231",
|
||||
# 'entry_id': "684157deab0c4c9ec636ed36", # 测试
|
||||
"data_list": email_data}
|
||||
api_instance.entry_data_batch_create(new_email_data)
|
||||
os.remove(self.write_path)
|
||||
return new_email_df
|
||||
|
||||
def up_to_BI(self, df):
|
||||
# 连接信息
|
||||
HS_DB_Config = Config.HS_DB_Config
|
||||
table_name = "thailand_store_data_email"
|
||||
|
||||
try:
|
||||
# 连接
|
||||
connection = pymysql.connect(
|
||||
host=HS_DB_Config["host"],
|
||||
user=HS_DB_Config["user"],
|
||||
password=HS_DB_Config["password"],
|
||||
database=HS_DB_Config["database"],
|
||||
charset='utf8mb4',
|
||||
)
|
||||
|
||||
print(f"成功连接 {HS_DB_Config["database"]}")
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
# 处理数据
|
||||
df = df.where(pd.notna(df), None) # 将NaN转换为None
|
||||
|
||||
# 生成插入语句
|
||||
columns = ', '.join(df.columns)
|
||||
placeholders = ', '.join(['%s'] * len(df.columns))
|
||||
insert_query = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
|
||||
|
||||
# 批量插入数据
|
||||
records = [tuple(row) for row in df.values]
|
||||
cursor.executemany(insert_query, records)
|
||||
connection.commit()
|
||||
|
||||
print(f"成功导入 {cursor.rowcount} 条记录到 {table_name} 表")
|
||||
|
||||
except Error as e:
|
||||
print(f"数据库操作出错: {e}")
|
||||
if connection:
|
||||
connection.rollback()
|
||||
finally:
|
||||
if connection:
|
||||
connection.close()
|
||||
|
||||
@classmethod
|
||||
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, "海外邮件推送")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
EmailProcessor.main()
|
||||
@@ -0,0 +1,196 @@
|
||||
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 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
|
||||
import json
|
||||
|
||||
logger = configure_task_logger()
|
||||
|
||||
# 获取已经配置好的错误任务日志记录器
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
# 初始化 API 实例和 Token
|
||||
yd_api_instance = YDAPI()
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
TOKEN = yd_api_instance.generateToken()
|
||||
print(TOKEN)
|
||||
|
||||
# 配置常量
|
||||
FORMID = "FORM-VJ866081CVI9E7ALB7WOO7BHPPQW25R99AWFL0" # 分子报备调整
|
||||
appType = "APP_UYZ0KG6L0CCNV80GZ66O" # F6客户服务
|
||||
systemToken = "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2" # 密钥
|
||||
|
||||
# 数据库配置
|
||||
DB_CONFIG = Config.HS_DB_Config
|
||||
|
||||
|
||||
class MoleculeReportingAdjustment:
|
||||
"""分子报备调整"""
|
||||
|
||||
def __init__(self):
|
||||
self.molecule_data_list = None
|
||||
self.structures = None
|
||||
self.denominator_data_list = None
|
||||
self.field_map = {
|
||||
"归属月份": "dateField_264kcmw",
|
||||
"门店编码": "textField_9rqmwyy",
|
||||
"门店名称": "textField_oxuvyp2",
|
||||
"公司名称": "textField_dqmsvkl",
|
||||
"续约后saas版本": "textField_1oil7le",
|
||||
"运营负责人": "textField_lxouajj",
|
||||
"区域经理": "textField_udayebj",
|
||||
"技术专家": "textField_49x98hm",
|
||||
"大区": "textField_a4niy40",
|
||||
"小区": "textField_s98potv",
|
||||
"省份": "textField_526wca0",
|
||||
"城市": "textField_pvk89jn",
|
||||
"收入类型": "selectField_alb3qo9",
|
||||
"关联订单编码": "textField_mtynj7n",
|
||||
"调整金额": "numberField_knq1ssd",
|
||||
"调整理由说明": "textField_6ysqrxw",
|
||||
"总部核对结果": "selectField_lfwb7dnn",
|
||||
"分子调整结果": "selectField_lfwb7dno",
|
||||
"是否上传衡石": "selectField_mceh174n",
|
||||
"总部调整备注": "textField_lfwb7dnp",
|
||||
}
|
||||
|
||||
def get_yida_data(self):
|
||||
# 获取分母报备数据
|
||||
molecule_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=1, n=100,
|
||||
appType=appType, systemToken=systemToken)
|
||||
self.molecule_data_list = []
|
||||
PAGES_two = molecule_data.get('totalCount') // 100 + 1
|
||||
for a in range(1, PAGES_two + 1):
|
||||
molecule_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=a, n=100,
|
||||
appType=appType, systemToken=systemToken)
|
||||
for item in molecule_data.get("data", []):
|
||||
|
||||
form_data = item.get("formData", {})
|
||||
# Transform the keys using field_map
|
||||
transformed_data = {}
|
||||
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 :
|
||||
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
|
||||
try:
|
||||
conn = mysql.connector.connect(**DB_CONFIG)
|
||||
cursor = conn.cursor()
|
||||
if many:
|
||||
cursor.executemany(sql, params)
|
||||
else:
|
||||
cursor.execute(sql, params or ())
|
||||
conn.commit()
|
||||
return cursor.fetchall() if fetch else cursor
|
||||
except Error as e:
|
||||
print(f"执行失败: {sql}\n错误: {e}")
|
||||
if conn: conn.rollback()
|
||||
return None
|
||||
finally:
|
||||
if conn and conn.is_connected():
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
def write_to_bi(self, df):
|
||||
# 数据库连接信息
|
||||
table_name = "f6_molecule_adjustment" # 替换为你的实际表名
|
||||
|
||||
# 建立数据库连接
|
||||
connection = mysql.connector.connect(
|
||||
host=DB_CONFIG["host"],
|
||||
user=DB_CONFIG["user"],
|
||||
password=DB_CONFIG["password"],
|
||||
database=DB_CONFIG["database"]
|
||||
)
|
||||
cursor = connection.cursor()
|
||||
|
||||
try:
|
||||
# 查询表列名
|
||||
cursor.execute(f"SHOW COLUMNS FROM {table_name}")
|
||||
columns_info = cursor.fetchall()
|
||||
db_columns = [col[0] for col in columns_info] # 提取列名
|
||||
df = df.replace([None, np.nan, pd.NA, 'nan', 'NaN', 'NAN', ''], None)
|
||||
# 保留 DataFrame 中与数据库列名匹配的列
|
||||
filtered_df = df[df.columns.intersection(db_columns)]
|
||||
|
||||
# 如果没有匹配的列,直接返回
|
||||
if filtered_df.empty:
|
||||
print("DataFrame 中没有与数据库表结构匹配的列。")
|
||||
return
|
||||
|
||||
# 筛选列之后,插入前处理 dict 类型
|
||||
filtered_df = filtered_df.copy()
|
||||
for col in filtered_df.columns:
|
||||
if filtered_df[col].apply(lambda x: isinstance(x, (dict, list)) if x is not None else False).any():
|
||||
filtered_df.loc[:, col] = filtered_df[col].apply(
|
||||
lambda x: json.dumps(x, ensure_ascii=False) if x is not None else x
|
||||
)
|
||||
|
||||
# 构建插入语句
|
||||
placeholders = ', '.join(['%s'] * len(filtered_df.columns))
|
||||
# 使用反引号避免特殊列明
|
||||
columns = ', '.join([f"`{col}`" for col in filtered_df.columns])
|
||||
insert_sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
|
||||
|
||||
# 将 DataFrame 写入数据库
|
||||
for _, row in filtered_df.iterrows():
|
||||
cursor.execute(insert_sql, tuple(row))
|
||||
|
||||
connection.commit()
|
||||
print(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")
|
||||
|
||||
except Exception as e:
|
||||
print("写入数据库时发生错误:", e)
|
||||
connection.rollback()
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
def clear_table(self):
|
||||
"""清空表数据"""
|
||||
if self.execute_sql("TRUNCATE TABLE f6_molecule_adjustment"):
|
||||
print("✅ 成功清空表数据")
|
||||
|
||||
def main(self):
|
||||
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
# step1:获取宜搭数据
|
||||
self.get_yida_data()
|
||||
|
||||
df = pd.DataFrame(self.molecule_data_list)
|
||||
df['归属月份'] = df['归属月份'].astype('Int64')
|
||||
df['归属月份'] = pd.to_datetime(df['归属月份'], unit='ms')
|
||||
|
||||
# step2:清空BI数据表
|
||||
self.clear_table()
|
||||
|
||||
# # step3:写入BI数据库
|
||||
self.write_to_bi(df)
|
||||
|
||||
common_module.send_task_status(task_start_time, "分子报备调整")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
molecule_reporting_adjustment = MoleculeReportingAdjustment()
|
||||
molecule_reporting_adjustment.main()
|
||||
@@ -0,0 +1,388 @@
|
||||
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 config import Config
|
||||
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()
|
||||
common_module = CommonModule()
|
||||
TOKEN = api_instanceyd.generateToken()
|
||||
|
||||
# 配置常量
|
||||
FORMID = "FORM-JD8668C1O2MV388PX5YIQGKMBEPS1EXV0UCWK0" # FPO需求提交
|
||||
appType = "APP_FE5IWP670JPRC5ZA6HK0" # FPO产品运营
|
||||
systemToken = "HP666C71ZLASJ0MPWC5ZOUA4AGDP17QU7TPRK92" # FPO产品运营
|
||||
BASE_URL = "https://f6car.aliwork.com" # 基础URL
|
||||
|
||||
# 目标表单配置
|
||||
TARGET_API_KEY = "675b900991ad2491c69389ca"
|
||||
TARGET_ENTRY_ID = "683fa187aeaf99ebb29faa63"
|
||||
|
||||
|
||||
class YDFpoJiandaoyun:
|
||||
"""
|
||||
宜搭FPO迁移到简道云
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.all_dict = pd.DataFrame() # 存储流程实例数据
|
||||
self.data_NGV = pd.DataFrame() # 存储NGV数据
|
||||
self.all_data = [] # 存储需要派发的数据
|
||||
self.success_count = 0
|
||||
self.fail_count = 0
|
||||
self.max_retries = 3 # API请求最大重试次数
|
||||
self.retry_delay = 1 # 重试延迟(秒)
|
||||
|
||||
def fetch_process_data(self):
|
||||
"""获取所有流程实例数据"""
|
||||
try:
|
||||
# 获取时间范围
|
||||
today_midnight = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
yesterday_midnight = today_midnight - timedelta(days=1)
|
||||
|
||||
start_time = yesterday_midnight.strftime("%Y-%m-%d") # 昨天0点
|
||||
end_time = today_midnight.strftime("%Y-%m-%d") # 今天0点
|
||||
|
||||
logger.info(f"开始时间: {start_time}, 结束时间: {end_time}")
|
||||
|
||||
# 创建DataFrame
|
||||
columns = ["超链接", "门店名称", "需求编号", "需求类型", "场景描述", "需求描述",
|
||||
"需求解决状态", "需求评审意见", "需求提出日期", "计划解决日期", "实际解决日期"]
|
||||
all_dict = pd.DataFrame(columns=columns)
|
||||
|
||||
# 获取总页数
|
||||
form_data = self._api_request_with_retry(
|
||||
api_instanceyd.read_processes,
|
||||
token=TOKEN,
|
||||
formUuid=FORMID,
|
||||
page=1,
|
||||
n=100,
|
||||
appType=appType,
|
||||
systemToken=systemToken
|
||||
)
|
||||
|
||||
if not form_data:
|
||||
error_task_logger.error("获取流程实例数据失败")
|
||||
return pd.DataFrame()
|
||||
|
||||
total_count = form_data.get('totalCount', 0)
|
||||
total_pages = total_count // 100 + (1 if total_count % 100 > 0 else 0)
|
||||
|
||||
logger.info(f"总共有 {total_count} 条记录,分为 {total_pages} 页")
|
||||
|
||||
# 分页获取数据
|
||||
for page in tqdm(range(1, total_pages + 1)):
|
||||
form_data = self._api_request_with_retry(
|
||||
api_instanceyd.read_processes,
|
||||
token=TOKEN,
|
||||
formUuid=FORMID,
|
||||
page=page,
|
||||
n=100,
|
||||
appType=appType,
|
||||
systemToken=systemToken
|
||||
)
|
||||
|
||||
if not form_data:
|
||||
error_task_logger.error(f"获取第 {page} 页数据失败")
|
||||
continue
|
||||
|
||||
self._process_page_data(form_data, all_dict)
|
||||
|
||||
logger.info(f"成功获取 {len(all_dict)} 条流程实例数据")
|
||||
return all_dict
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"获取流程实例数据时发生错误: {e}", exc_info=True)
|
||||
return pd.DataFrame()
|
||||
|
||||
def _process_page_data(self, form_data, all_dict):
|
||||
"""处理单页流程实例数据"""
|
||||
for file in form_data.get("data", []):
|
||||
try:
|
||||
# 构建URL
|
||||
url = f"{BASE_URL}/{appType}/formDetail/{FORMID}?formInstId={file['formInstanceId']}"
|
||||
|
||||
# 添加新行
|
||||
new_row = pd.Series([
|
||||
url,
|
||||
file['formData'].get('selectField_kwcxm069', ''),
|
||||
file['formData'].get('textField_krydg6af', ''),
|
||||
file['formData'].get('selectField_kwd5rp7s', ''),
|
||||
file['formData'].get('textareaField_krrhmeuc', ''),
|
||||
file['formData'].get('textareaField_krrhmeud', ''),
|
||||
file['formData'].get('selectField_krrhmevo', ''),
|
||||
file['formData'].get('textareaField_krrhmevm', ''),
|
||||
file['formData'].get('dateField_krrhmeue', ''),
|
||||
file['formData'].get('dateField_krrhmex6', ''),
|
||||
file['formData'].get('dateField_krrhmex9', '')
|
||||
], index=all_dict.columns)
|
||||
all_dict.loc[len(all_dict)] = new_row
|
||||
except KeyError as e:
|
||||
error_task_logger.error(f"处理记录时缺少字段: {e}")
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"处理记录时出错: {e}")
|
||||
|
||||
def NGV_data(self):
|
||||
"""获取NGV数据"""
|
||||
try:
|
||||
logger.info("开始获取NGV数据")
|
||||
data_NGV = common_module.get_ngv_details(days_back=1)
|
||||
logger.info(f"成功获取 {len(data_NGV)} 条NGV数据")
|
||||
return data_NGV
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"获取NGV数据时发生错误: {e}", exc_info=True)
|
||||
return pd.DataFrame()
|
||||
|
||||
def match_and_update(self):
|
||||
"""根据门店名称匹配两个DataFrame,并更新all_dict"""
|
||||
try:
|
||||
if self.all_dict.empty or self.data_NGV.empty:
|
||||
logger.warning("all_dict 或 data_NGV 为空,无法进行匹配")
|
||||
return self.all_dict
|
||||
|
||||
# 创建一个映射字典,键是org_name,值是(id_own_org, id_own_group)元组
|
||||
mapping_dict = {}
|
||||
for _, row in self.data_NGV.iterrows():
|
||||
mapping_dict[row['org_name']] = (row['id_own_org'], row['id_own_group'])
|
||||
|
||||
# 创建新的列来存储匹配结果
|
||||
self.all_dict['id_own_org'] = None
|
||||
self.all_dict['id_own_group'] = None
|
||||
|
||||
# 匹配计数
|
||||
match_count = 0
|
||||
|
||||
# 遍历all_dict,根据门店名称查找对应的id
|
||||
for idx, row in self.all_dict.iterrows():
|
||||
store_name = row['门店名称']
|
||||
if store_name in mapping_dict:
|
||||
org_id, group_id = mapping_dict[store_name]
|
||||
self.all_dict.at[idx, 'id_own_org'] = org_id
|
||||
self.all_dict.at[idx, 'id_own_group'] = group_id
|
||||
match_count += 1
|
||||
|
||||
logger.info(f"匹配完成: 共 {len(self.all_dict)} 条记录,成功匹配 {match_count} 条")
|
||||
return self.all_dict
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"匹配数据时发生错误: {e}", exc_info=True)
|
||||
return self.all_dict
|
||||
|
||||
def write_in(self):
|
||||
"""将处理后的数据写入表单"""
|
||||
if self.all_dict.empty:
|
||||
logger.warning("all_dict 为空,没有数据可写入")
|
||||
return
|
||||
|
||||
self.success_count = 0
|
||||
self.fail_count = 0
|
||||
|
||||
for index_num, row in tqdm(self.all_dict.iterrows(), total=len(self.all_dict)):
|
||||
try:
|
||||
payload_dict = self._build_payload_dict(row)
|
||||
self.all_data.append(payload_dict)
|
||||
self.success_count += 1
|
||||
|
||||
except Exception as e:
|
||||
self.fail_count += 1
|
||||
error_task_logger.error(f"处理记录 #{index_num} 时发生错误: {e}", exc_info=True)
|
||||
|
||||
return self.all_data
|
||||
|
||||
def _build_payload_dict(self, row):
|
||||
"""构建请求数据字典"""
|
||||
|
||||
return {
|
||||
"_widget_1749000583446": {"value": row["门店名称"]},
|
||||
"_widget_1749000583447": {"value": row["超链接"]},
|
||||
"_widget_1749006049130": {"value": row["需求编号"]},
|
||||
"_widget_1749006049131": {"value": row["需求类型"]},
|
||||
"_widget_1749006049132": {"value": row["场景描述"]},
|
||||
"_widget_1749006049133": {"value": row["需求描述"]},
|
||||
"_widget_1749006049134": {"value": row["需求解决状态"]},
|
||||
"_widget_1749006049135": {"value": row["id_own_org"]},
|
||||
"_widget_1749006049136": {"value": row["id_own_group"]},
|
||||
"_widget_1749019791181": {"value": row["需求评审意见"]},
|
||||
"_widget_1749019791182": {"value": row["需求提出日期"]},
|
||||
"_widget_1749019791183": {"value": row["计划解决日期"]},
|
||||
"_widget_1749019791184": {"value": row["实际解决日期"]}
|
||||
}
|
||||
|
||||
def _build_request_payload(self, payload_dict):
|
||||
"""构建完整请求负载"""
|
||||
UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
|
||||
return {
|
||||
"api_key": TARGET_API_KEY,
|
||||
"entry_id": TARGET_ENTRY_ID,
|
||||
"is_start_workflow": "true",
|
||||
"data": payload_dict,
|
||||
"transaction_id": UUid
|
||||
}
|
||||
|
||||
def _api_request_with_retry(self, api_func, *args, **kwargs):
|
||||
"""API请求重试机制"""
|
||||
for attempt in range(self.max_retries):
|
||||
try:
|
||||
result = api_func(*args, **kwargs)
|
||||
return result
|
||||
except Exception as e:
|
||||
if attempt < self.max_retries - 1:
|
||||
logger.warning(f"API请求失败,正在重试 ({attempt + 1}/{self.max_retries}): {e}")
|
||||
# time.sleep(self.retry_delay)
|
||||
self.retry_delay *= 2 # 指数退避
|
||||
else:
|
||||
error_task_logger.error(f"API请求失败,已达到最大重试次数: {e}", exc_info=True)
|
||||
return None
|
||||
|
||||
def clear_existing_data(self):
|
||||
"""清除目标表单中的现有数据"""
|
||||
try:
|
||||
logger.info("开始清除现有数据")
|
||||
|
||||
# 获取现有数据ID
|
||||
payload = {"api_key": TARGET_API_KEY, "entry_id": TARGET_ENTRY_ID}
|
||||
get_ids = self._api_request_with_retry(
|
||||
api_instance.entry_data_list,
|
||||
payload
|
||||
)
|
||||
|
||||
if not get_ids:
|
||||
logger.warning("获取现有数据ID失败")
|
||||
return
|
||||
|
||||
data_list = get_ids.get("data", [])
|
||||
if not data_list:
|
||||
logger.info("目标表单中没有现有数据")
|
||||
return
|
||||
|
||||
delete_ids = [item["_id"] for item in data_list]
|
||||
logger.info(f"将删除 {len(delete_ids)} 条现有记录")
|
||||
|
||||
# 批量删除
|
||||
delete_payload = {
|
||||
"api_key": TARGET_API_KEY,
|
||||
"entry_id": TARGET_ENTRY_ID,
|
||||
"data_ids": delete_ids
|
||||
}
|
||||
|
||||
delete_result = self._api_request_with_retry(
|
||||
api_instance.entry_data_batch_delete,
|
||||
delete_payload
|
||||
)
|
||||
|
||||
if delete_result and delete_result.get("success", False):
|
||||
logger.info("成功清除现有数据")
|
||||
else:
|
||||
error_msg = delete_result.get('message', '未知错误') if delete_result else '无响应'
|
||||
error_task_logger.error(f"清除现有数据失败: {error_msg}")
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"清除现有数据时发生错误: {e}", exc_info=True)
|
||||
|
||||
def batch_create_entries(self,task_start_time):
|
||||
"""批量创建条目"""
|
||||
try:
|
||||
if not self.all_data:
|
||||
logger.warning("没有数据可创建条目")
|
||||
return False
|
||||
|
||||
UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
|
||||
# task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
routine_follow_up_payload = {
|
||||
"api_key": TARGET_API_KEY,
|
||||
"entry_id": TARGET_ENTRY_ID,
|
||||
"is_start_workflow": "true",
|
||||
"data_list": self.all_data,
|
||||
"transaction_id": UUid
|
||||
}
|
||||
|
||||
res = api_instance.entry_data_batch_create(routine_follow_up_payload)
|
||||
logger.info(f"创建结果:{res}")
|
||||
|
||||
# 发送任务状态
|
||||
common_module.send_task_status(task_start_time, "宜搭FPO实例同步简道云")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"批量创建条目时发生错误: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def main(self):
|
||||
"""主函数,协调各个处理步骤"""
|
||||
task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
logger.info("=" * 50)
|
||||
logger.info("开始执行时间消耗流程处理")
|
||||
logger.info("=" * 50)
|
||||
|
||||
try:
|
||||
# Step 1: 获取流程实例
|
||||
logger.info("步骤1: 获取流程实例数据")
|
||||
self.all_dict = self.fetch_process_data()
|
||||
|
||||
if self.all_dict.empty:
|
||||
logger.warning("未获取到流程实例数据,终止执行")
|
||||
return
|
||||
|
||||
# Step 2: 获取NGV数据
|
||||
logger.info("步骤2: 获取NGV数据")
|
||||
self.data_NGV = self.NGV_data()
|
||||
|
||||
if self.data_NGV.empty:
|
||||
logger.warning("未获取到NGV数据,终止执行")
|
||||
return
|
||||
|
||||
# Step 3: 匹配数据
|
||||
logger.info("步骤3: 匹配流程实例与NGV数据")
|
||||
self.all_dict = self.match_and_update()
|
||||
|
||||
# Step 4: 清除之前的数据
|
||||
logger.info("步骤4: 清除目标表单中的现有数据")
|
||||
self.clear_existing_data()
|
||||
|
||||
# Step 5: 写入表单
|
||||
logger.info("步骤5: 将处理后的数据写入表单")
|
||||
self.write_in()
|
||||
|
||||
# Step 6: 批量创建条目
|
||||
logger.info("步骤6: 批量创建条目")
|
||||
success = self.batch_create_entries(task_start_time)
|
||||
|
||||
logger.info("=" * 50)
|
||||
logger.info(
|
||||
f"处理完成: 共处理 {len(self.all_dict)} 条记录,成功 {self.success_count} 条,失败 {self.fail_count} 条")
|
||||
logger.info(f"批量创建结果: {'成功' if success else '失败'}")
|
||||
logger.info("=" * 50)
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"执行过程中发生错误: {e}", exc_info=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
processor = YDFpoJiandaoyun()
|
||||
processor.main()
|
||||
@@ -0,0 +1,820 @@
|
||||
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
|
||||
|
||||
api_instance = API()
|
||||
common_module = CommonModule()
|
||||
logger = configure_task_logger()
|
||||
error_task_logger = configure_error_task_logger()
|
||||
|
||||
|
||||
class NewServicesRevisitTest:
|
||||
"""
|
||||
用于处理新签服务回访的类。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# 初始化所有数据属性
|
||||
self.get_feature_usage = None
|
||||
self.saas_create_time = None
|
||||
self.index = None
|
||||
self.date_one = None
|
||||
self.data_NGV_S = None
|
||||
self.date_list = None
|
||||
self.Smart_detection = None
|
||||
self.service_remind = None
|
||||
self.NGV_data_list = None
|
||||
self.permissions_table = None
|
||||
self.staff_id_list = None
|
||||
self.json_list = []
|
||||
self.policy_recognition = None
|
||||
self.widget_list = None
|
||||
self.private_domain = None
|
||||
self.public_domain = None
|
||||
self.public_domain_list = None
|
||||
self.different_industries = None
|
||||
self.different_industries_list = None
|
||||
self.groupnotification = None
|
||||
|
||||
def calculate_date_one(self, start_offset=0):
|
||||
"""
|
||||
计算从当前日期(或指定偏移量的日期)开始,往前遍历遇到date_list中日期的次数。
|
||||
|
||||
参数:
|
||||
- start_offset: 从当前日期起始的天数偏移量,默认为0(即今天)。负数表示过去,正数表示未来。
|
||||
|
||||
返回:
|
||||
- date_one: 遍历到date_list中日期的次数。
|
||||
"""
|
||||
jdy_date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
jdy_start_time = datetime.datetime.now().strftime("%Y-%m-%d ")
|
||||
# 设置起始日期
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=start_offset)
|
||||
|
||||
# 初始化计数器
|
||||
date_one = 1
|
||||
print("当前日期:", now_time.strftime("%Y-%m-%d"))
|
||||
# 检查起始日期是否在date_list中
|
||||
if now_time.strftime("%Y-%m-%d") in self.date_list:
|
||||
date_one = 0
|
||||
print("开始次数:", date_one)
|
||||
|
||||
else:
|
||||
# 遍历日期
|
||||
for i in range(1, 10):
|
||||
new_date = now_time + datetime.timedelta(days=-i)
|
||||
new_date_str = new_date.strftime("%Y-%m-%d")
|
||||
print("遍历日期:", new_date_str)
|
||||
if new_date_str in self.date_list:
|
||||
date_one += 1
|
||||
print("节假日期:", new_date_str)
|
||||
else:
|
||||
break
|
||||
|
||||
print("遍历次数:", date_one)
|
||||
return date_one
|
||||
|
||||
@staticmethod
|
||||
def download_url_content(url, save_path):
|
||||
"""
|
||||
下载指定 URL 的内容并保存到本地文件。简道云图片下载
|
||||
|
||||
:param url: 要下载内容的 URL
|
||||
:param save_path: 保存文件的路径
|
||||
"""
|
||||
try:
|
||||
# 发送 GET 请求以获取内容
|
||||
response = requests.get(url, stream=True)
|
||||
response.raise_for_status() # 如果响应状态码不是 200,抛出异常
|
||||
|
||||
# 确保保存目录存在
|
||||
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
||||
|
||||
# 将内容写入文件
|
||||
with open(save_path, 'wb') as file:
|
||||
for chunk in response.iter_content(chunk_size=8192): # 分块写入,避免占用过多内存
|
||||
if chunk: # 过滤掉空块
|
||||
file.write(chunk)
|
||||
|
||||
print(f"文件已成功保存到 {save_path}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"下载失败: {e}")
|
||||
except Exception as e:
|
||||
print(f"发生错误: {e}")
|
||||
|
||||
def load_all_data(self):
|
||||
"""加载所有必要的数据表"""
|
||||
# 省市区人员关系表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676512ac3e54dc3159460c0a"}
|
||||
json_dict = api_instance.entry_data_list(payload)
|
||||
self.json_list = json_dict.get("data")
|
||||
|
||||
# 获取简道云员工id
|
||||
payload = {"api_key": "6694d3c4fcb69ca9a111a6c4",
|
||||
"entry_id": "6769204a1902c9341340a1bc",
|
||||
}
|
||||
staff_id = api_instance.entry_data_list(payload)
|
||||
self.staff_id_list = staff_id.get("data") # api请求格式,将数据封装在data字典里
|
||||
|
||||
# 获取权限表信息
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675b96c14e839f90fef1647c"}
|
||||
self.permissions_table = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取NGV数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "675bb02bd2d53c2034c665e4"}
|
||||
self.NGV_data_list = api_instance.entry_data_list(payload).get("data", [])
|
||||
# print("NGV获取后的类型:", type(self.NGV_data_list))
|
||||
|
||||
# 获取服务提醒-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb7bda3029720f1083e99"}
|
||||
self.service_remind = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取智能检测-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "676bb99649ab3ac975af6e39"}
|
||||
self.Smart_detection = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取功能使用情况表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6763bbf657bd8fb76fcb41b2"}
|
||||
self.get_feature_usage = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
# 获取保单识别表
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "6773a60d30ed87ff9f68d3c5"}
|
||||
self.policy_recognition = api_instance.entry_data_list(payload).get("data")
|
||||
# 提取 _widget_1735632397600 的值并存储在列表中
|
||||
self.widget_list = [item['_widget_1735632397600'] for item in self.policy_recognition]
|
||||
|
||||
# 获取私域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0f0fae622896749ba5087"}
|
||||
self.private_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742795002375 的值并存储在列表中
|
||||
# self.private_domain = [item['_widget_1742795002375'] for item in self.private_domain]
|
||||
|
||||
# 获取公域小程序-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e0c702c8f603b997980999"}
|
||||
self.public_domain = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.public_domain_list = [item['_widget_1742784257506'] for item in self.public_domain]
|
||||
|
||||
# 获取异业合作-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e24fdd8dfcfa918e17c30b"}
|
||||
self.different_industries = api_instance.entry_data_list(payload).get("data", [])
|
||||
# 提取 _widget_1742784257506 的值并存储在列表中
|
||||
self.different_industries_list = [item['_widget_1742884829007'] for item in self.different_industries]
|
||||
|
||||
# 获取短信-数据支持表单数据
|
||||
payload = {"api_key": "675b900991ad2491c69389ca", "entry_id": "67e5107198ba1b20d5df3974"}
|
||||
self.groupnotification = api_instance.entry_data_list(payload).get("data", [])
|
||||
|
||||
@staticmethod
|
||||
def build_index(json_list):
|
||||
"""构建省市区人员索引"""
|
||||
index = {}
|
||||
# print(json_list)
|
||||
for json_item in json_list:
|
||||
# json_item = json_item.get("data")
|
||||
# print(json_item)
|
||||
try:
|
||||
key = (json_item['_widget_1734677164861'], json_item['_widget_1734677164862'],
|
||||
json_item['_widget_1734677164863']) # 省市区
|
||||
if '_widget_1734677164871' not in json_item: # 日常回访客服
|
||||
raise KeyError("缺少 '日常回访客服' 键")
|
||||
index[key] = json_item
|
||||
except KeyError as e:
|
||||
print(f"警告:{e},跳过该条记录: {json_item}")
|
||||
continue
|
||||
return index
|
||||
|
||||
@staticmethod
|
||||
def find_customer_service(province_name, city_name, area_name, index):
|
||||
"""根据省市区查找客服"""
|
||||
key = (province_name, city_name, area_name)
|
||||
# print(index)
|
||||
if key not in index:
|
||||
return "数据缺失: 未找到对应的日常回访客服"
|
||||
|
||||
return index[key]
|
||||
|
||||
@staticmethod
|
||||
def remove_parentheses(text: str) -> str:
|
||||
"""使用正则表达式匹配并去除括号及其内容"""
|
||||
# \s* 表示匹配零个或多个空白字符(处理括号前后可能存在的空格)
|
||||
# $ 和 $ 分别表示匹配左括号和右括号
|
||||
# 中间的 .*? 表示非贪婪地匹配任意数量的字符(包括没有字符的情况)
|
||||
cleaned_text = re.sub(r'\s*$.*?$\s*', '', text)
|
||||
# 为了确保同时处理中文括号,再进行一次替换
|
||||
cleaned_text = re.sub(r'\s*(.*?)\s*', '', cleaned_text)
|
||||
return cleaned_text.strip() # 去除两端多余的空白字符
|
||||
|
||||
@staticmethod
|
||||
def get_staff_id(row_item, name):
|
||||
"""辅助函数,用于获取员工ID"""
|
||||
if str(row_item["_widget_1734942794144"]) == str(name): # 检查姓名是否匹配
|
||||
return row_item["_widget_1734942794145"] # 返回员工ID
|
||||
return None
|
||||
|
||||
def assign_customer_service(self, province_name, city_name, area_name, index):
|
||||
"""根据省市区派发给日常回访客服"""
|
||||
try:
|
||||
customer_service_info = self.find_customer_service(province_name, city_name, area_name, index)
|
||||
|
||||
# 定义一个辅助函数,用于安全地获取多层字段中的 username
|
||||
def safe_get_username(data, key):
|
||||
try:
|
||||
if isinstance(data, dict):
|
||||
return data.get(key, {}).get('username', "")
|
||||
return ""
|
||||
except:
|
||||
return ""
|
||||
|
||||
relationship_manager = safe_get_username(customer_service_info, '_widget_1734677164864')
|
||||
customer_service = safe_get_username(customer_service_info, '_widget_1734677164871')
|
||||
technician = safe_get_username(customer_service_info, '_widget_1734677164866')
|
||||
area_manager = safe_get_username(customer_service_info, '_widget_1734677164865')
|
||||
return relationship_manager, customer_service, technician, area_manager
|
||||
except Exception as e:
|
||||
print(f"Error finding customer service: {e}")
|
||||
return "分配失败,请检查", "分配失败,请检查", "分配失败,请检查"
|
||||
|
||||
def prepare_data(self):
|
||||
"""准备基础数据"""
|
||||
# Step 1: 加载所有数据表
|
||||
self.load_all_data()
|
||||
|
||||
# Step 2: 获取节假日列表
|
||||
self.date_list = common_module.get_holiday_list()
|
||||
|
||||
# Step 3: 获取NGV数据
|
||||
self.data_NGV_S = common_module.get_ngv_details(days_back=1).astype(str)
|
||||
|
||||
# Step 4: 计算日期偏移
|
||||
self.date_one = self.calculate_date_one(start_offset=0)
|
||||
|
||||
# Step 5: 构建索引
|
||||
self.index = self.build_index(self.json_list)
|
||||
|
||||
# Step 6: 设置时间偏移常量
|
||||
self.saas_create_time_180 = 173
|
||||
self.saas_create_time_90 = 83
|
||||
|
||||
def filter_and_process_data(self):
|
||||
"""过滤和处理数据"""
|
||||
# Step 1: 准备数据
|
||||
self.prepare_data()
|
||||
|
||||
print("开始运行主流程")
|
||||
for i in range(0, self.date_one):
|
||||
# Step 2: 计算当前处理日期
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(days=-i)
|
||||
today_180 = now_time + datetime.timedelta(days=-self.saas_create_time_180)
|
||||
formatted_today_180 = today_180.strftime("%Y-%m-%d")
|
||||
today_90 = now_time + datetime.timedelta(days=-self.saas_create_time_90)
|
||||
formatted_today_90 = today_90.strftime("%Y-%m-%d")
|
||||
print("SaaS开户回访日期:", formatted_today_180, formatted_today_90)
|
||||
|
||||
# Step 3: 数据预处理
|
||||
data_NGV = self.data_NGV_S.copy()
|
||||
data_NGV = data_NGV.apply(lambda series: series.apply(
|
||||
lambda x: '' if pd.isna(x) or x in ['NA', 'None', ''] else x))
|
||||
|
||||
# Step 4: 计算最佳版本、分层和等级
|
||||
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)}
|
||||
|
||||
# 添加排序列
|
||||
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)
|
||||
|
||||
# 找到最佳值
|
||||
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']
|
||||
|
||||
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_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')
|
||||
)
|
||||
|
||||
data_NGV = data_NGV.merge(best_values, on='id_own_group', how='left')
|
||||
|
||||
# Step 5: 过滤数据
|
||||
condition = (data_NGV['is_main_org'] == 1) & (data_NGV['org_status'] == '过期')
|
||||
ngvv2 = data_NGV[condition]
|
||||
|
||||
data_NGV_V2 = data_NGV.copy()
|
||||
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["条件"]]
|
||||
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(edition_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')
|
||||
|
||||
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)
|
||||
|
||||
# Step 6: 设置跟进阶段和主要目的
|
||||
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
|
||||
|
||||
data_NGV = data_NGV.apply(set_columns, axis=1)
|
||||
print("SaaS开户回访人数:", len(data_NGV))
|
||||
|
||||
# Step 7: 重置索引
|
||||
data_NGV = data_NGV.reset_index(drop=True)
|
||||
|
||||
# Step 8: 处理每个门店数据
|
||||
self.process_shop_data(data_NGV, formatted_today_180, formatted_today_90)
|
||||
|
||||
def process_shop_data(self, data_NGV, formatted_today_180, formatted_today_90):
|
||||
"""处理每个门店的数据"""
|
||||
for index_num, row in data_NGV.iterrows():
|
||||
try:
|
||||
# Step 1: 准备基础数据
|
||||
payload_dict = {}
|
||||
saas_use_year = re.findall(r'第([0-9]+)年', row["saas_use_year"])[0]
|
||||
|
||||
# Step 2: 获取员工ID
|
||||
NGV_roles = {
|
||||
'relationship_manager': row['service_impl_principal'],
|
||||
'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
|
||||
|
||||
# Step 3: 分配回访人员
|
||||
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 or not technician:
|
||||
relationship_manager, _, technician, _ = self.assign_customer_service(
|
||||
row['province_name'], row['city_name'], row['area_name'], self.index
|
||||
)
|
||||
|
||||
if row["group_grade"] in ["普通客户(VIP)", "重要客户(SVIP)"]:
|
||||
payload_dict["_widget_1734590278288"] = {"value": relationship_manager} # 跟进人是运营负责人
|
||||
else:
|
||||
payload_dict["_widget_1734590278288"] = {"value": technician} # 跟进人是技术专家
|
||||
else:
|
||||
salesmen = NGV_roles['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"] in ["普通客户(VIP)", "重要客户(SVIP)"]:
|
||||
payload_dict["_widget_1734590278288"] = {"value": customer_service}
|
||||
else:
|
||||
payload_dict["_widget_1734590278288"] = {"value": technician}
|
||||
|
||||
# 其他成员字段赋值
|
||||
payload_dict.update({
|
||||
"_widget_1734590278289": {"value": relationship_manager}, # 运营负责人
|
||||
"_widget_1734590278290": {"value": area_manager}, # 区域经理
|
||||
"_widget_1734590278291": {"value": technician}, # 技术专家
|
||||
"_widget_1735290738545": {"value": salesmen} # 销售负责人
|
||||
})
|
||||
|
||||
# Step 4: 处理特殊逻辑
|
||||
if payload_dict.get("_widget_1734590278288") == "02414917880947": # 如果跟进人是殷浩
|
||||
payload_dict["_widget_1734590278288"] = {"value": "051612246035720178"} # 跟进人是赵柄诚
|
||||
|
||||
# Step 5: 获取权限信息
|
||||
group_grade = re.sub(r'([^)]*)', '', row['max_group_grade'])
|
||||
if not row['saas_customer_type'] or row['saas_customer_type'] in ['NA', 'None']:
|
||||
row['saas_customer_type'] = "F"
|
||||
|
||||
NGV_store_level_key = group_grade + row['max_saas_edition'] + row['max_saas_customer_type']
|
||||
|
||||
# Step 6: 处理权限表逻辑...
|
||||
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},
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
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"]: # 下次是否推荐 功能使用情况表
|
||||
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"]: # 下次是否跟进
|
||||
print(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": "是"}})
|
||||
|
||||
break
|
||||
|
||||
if not Billing:
|
||||
print(f"权限表请求失败或者权限表无对应关系,权限唯一值是:{NGV_store_level_key}")
|
||||
|
||||
# 根据NGV内容给出默认值
|
||||
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"
|
||||
] # 智能检测 是否使用
|
||||
|
||||
# 初始化默认值为"否"
|
||||
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:是否拥有
|
||||
else:
|
||||
payload_dict.update({'_widget_1735106258141': {"value": "否"}}) # SYXCX:是否拥有
|
||||
except Exception as e:
|
||||
print(f"私域小程序:Error finding customer service: {e}")
|
||||
|
||||
# 公域小程序:根据是否开通微信小程序判断是否使用,旗舰版及以上算拥有
|
||||
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:
|
||||
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}")
|
||||
|
||||
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}")
|
||||
|
||||
# Step 7: 创建回访记录
|
||||
self.create_revisit_record(row, payload_dict)
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"处理门店数据时出错: {e}")
|
||||
continue
|
||||
|
||||
def create_revisit_record(self, row, payload_dict):
|
||||
"""创建回访记录"""
|
||||
# Step 1: 获取关联数据
|
||||
NGV_data_id = None
|
||||
for NGV_Data in self.NGV_data_list:
|
||||
if row["org_code"] == NGV_Data.get("_widget_1734062123071"):
|
||||
NGV_data_id = NGV_Data.get("_id")
|
||||
try:
|
||||
png_url = NGV_Data.get('_widget_1742890765211', {})[0].get('url', "")
|
||||
except:
|
||||
png_url = ""
|
||||
|
||||
# Step 2: 处理图片上传
|
||||
upload_key = None
|
||||
UUid = time.strftime("%Y%m%d%H%M%S", time.localtime())
|
||||
if png_url:
|
||||
save_dir = "sampleCloud"
|
||||
os.makedirs(save_dir, exist_ok=True)
|
||||
save_path = fr'{save_dir}\png\{UUid}.png'
|
||||
self.download_url_content(png_url, 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")
|
||||
|
||||
# Step 3: 设置分发时间
|
||||
distribution_date = datetime.datetime.now(datetime.timezone.utc)
|
||||
distribution_date = distribution_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
|
||||
|
||||
# Step 4: 完善payload
|
||||
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]} # 门头照片
|
||||
})
|
||||
|
||||
# Step 5: 创建记录
|
||||
routine_follow_up_payload = {
|
||||
"api_key": "675b900991ad2491c69389ca",
|
||||
# "entry_id": "675b9c63925cd404038a6b86", # 日常回访表单
|
||||
"entry_id": "6850e88ebdfde576a2e91a59", # 测试表单
|
||||
"is_start_workflow": "true",
|
||||
"data": payload_dict,
|
||||
"transaction_id": UUid
|
||||
}
|
||||
|
||||
res = api_instance.data_batch_create(routine_follow_up_payload)
|
||||
logger.info(f"创建结果:{res}")
|
||||
|
||||
def main(self):
|
||||
"""主入口方法"""
|
||||
# Step 1: 记录任务开始时间
|
||||
task_start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
try:
|
||||
# Step 2: 过滤和处理数据
|
||||
self.filter_and_process_data()
|
||||
|
||||
# Step 3: 发送任务状态通知
|
||||
common_module.send_task_status(task_start_time, "新签客户回访测试")
|
||||
logger.info("任务执行成功")
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"任务执行失败: {e}")
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = NewServicesRevisitTest()
|
||||
start.main()
|
||||
Reference in New Issue
Block a user