NGV换源
This commit is contained in:
+114
-18
@@ -5,7 +5,8 @@ from api import API
|
||||
from back_ground_module import CommonModule
|
||||
from log_config import configure_task_logger, configure_error_task_logger
|
||||
from collections import defaultdict
|
||||
|
||||
from datetime import datetime, timezone, timedelta, date, UTC
|
||||
from config import Config
|
||||
logger = configure_task_logger()
|
||||
error_task_logger = configure_error_task_logger()
|
||||
api_instance = API()
|
||||
@@ -14,7 +15,81 @@ output_dir = "output" # 设置输出目录
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
|
||||
import pandas as pd
|
||||
import psycopg2
|
||||
from datetime import datetime, timedelta, date
|
||||
import os
|
||||
def get_renewal_details():
|
||||
"""
|
||||
从固定的数据库中获取续约待办数据,先拉全量(指定 date_id),再用 CSV 中的门店编码在内存中过滤
|
||||
"""
|
||||
try:
|
||||
# 1. 从 CSV 文件中读取门店编码
|
||||
csv_path = r"D:\Idea Project\SaaS_V1.7\test\output\expanded_yd_data.csv"
|
||||
if not os.path.exists(csv_path):
|
||||
error_task_logger.error(f"CSV 文件不存在: {csv_path}")
|
||||
return pd.DataFrame()
|
||||
|
||||
store_df = pd.read_csv(csv_path, dtype=str)
|
||||
if "textField_ksydghqw" not in store_df.columns:
|
||||
error_task_logger.error("CSV 文件中缺少列 'textField_ksydghqw'")
|
||||
return pd.DataFrame()
|
||||
|
||||
store_codes = set(store_df["textField_ksydghqw"].dropna().unique()) # 转为 set 提升查找效率
|
||||
if not store_codes:
|
||||
error_task_logger.warning("CSV 中未找到有效的门店编码")
|
||||
return pd.DataFrame()
|
||||
|
||||
# 2. 连接数据库
|
||||
conn = psycopg2.connect(**Config.CONN_INFO)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 获取前两天的 date_id(整数格式 YYYYMMDD)
|
||||
now_time = datetime.now()
|
||||
yes_time = now_time + timedelta(days=-2)
|
||||
yes_time_nyr = int(yes_time.strftime('%Y%m%d'))
|
||||
|
||||
# 3. 构造 SQL 查询:不再包含 org_code 过滤
|
||||
sql = """
|
||||
SELECT *
|
||||
FROM "public"."holo_ads_report_saas_profile_ngv_detail_d"
|
||||
WHERE "date_id" = %s
|
||||
"""
|
||||
|
||||
# 执行查询(只传 date_id)
|
||||
cursor.execute(sql, (yes_time_nyr,))
|
||||
rows = cursor.fetchall()
|
||||
all_fields = cursor.description
|
||||
|
||||
# 转换为 DataFrame
|
||||
col = [i[0] for i in all_fields]
|
||||
data_NGV = pd.DataFrame(rows, columns=col) if rows else pd.DataFrame(columns=col)
|
||||
|
||||
# 关闭连接
|
||||
cursor.close()
|
||||
conn.close()
|
||||
|
||||
# 4. 在内存中用 store_codes 过滤 org_code
|
||||
if "org_code" not in data_NGV.columns:
|
||||
error_task_logger.error("数据库结果中缺少 'org_code' 字段")
|
||||
return pd.DataFrame()
|
||||
|
||||
# 确保 org_code 是字符串类型(与 store_codes 一致)
|
||||
data_NGV = data_NGV.copy() # 避免 SettingWithCopyWarning
|
||||
data_NGV["org_code"] = data_NGV["org_code"].astype(str)
|
||||
|
||||
# 过滤:只保留 org_code 在 store_codes 中的行
|
||||
filtered_data = data_NGV[data_NGV["org_code"].isin(store_codes)].reset_index(drop=True)
|
||||
|
||||
return filtered_data
|
||||
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"获取续约待办数据时出错: {e}", exc_info=True)
|
||||
return pd.DataFrame()
|
||||
|
||||
class RenewalToDo:
|
||||
"""续约回访待办派发"""
|
||||
|
||||
def __init__(self):
|
||||
self.renewal_data_list = None
|
||||
self.cyclic_increasing = None
|
||||
@@ -84,6 +159,8 @@ class RenewalToDo:
|
||||
"流程状态": "_widget_1765352838610",
|
||||
"经营模式": "_widget_1765964381952",
|
||||
"公司等级": "_widget_1766130435561",
|
||||
"公司id": "_widget_1766631811839",
|
||||
"订单商品名称": "_widget_1766730385209",
|
||||
"提交人": "creator",
|
||||
"提交时间": "createTime",
|
||||
"更新时间": "updateTime"
|
||||
@@ -101,6 +178,7 @@ class RenewalToDo:
|
||||
"group_grade": "公司等级",
|
||||
"technician": "运营专家",
|
||||
"manage_model": "经营模式",
|
||||
"id_own_group": "公司id",
|
||||
}
|
||||
self.subform_field_map = {
|
||||
"商品名称": "_widget_1764820541719",
|
||||
@@ -112,7 +190,7 @@ class RenewalToDo:
|
||||
"续约后订单编码": "_widget_1764820541725",
|
||||
# 根据实际需要添加更多字段
|
||||
}
|
||||
self.renewal_list_map ={
|
||||
self.renewal_list_map = {
|
||||
|
||||
}
|
||||
|
||||
@@ -123,7 +201,9 @@ class RenewalToDo:
|
||||
"""
|
||||
|
||||
# 数据库获取续约回访数据
|
||||
self.data_NGV = pd.read_csv(os.path.join(output_dir, "data_NGV.csv"), encoding="gbk")
|
||||
self.data_NGV = common_module.get_renewal_details()
|
||||
# self.data_NGV = get_renewal_details() # 历史数据
|
||||
self.data_NGV.to_csv("D:\\Idea Project\\SaaS_V1.7\\test\\output\data_NGV1.csv")
|
||||
|
||||
# 获取加盟商信息
|
||||
self.franchisee = common_module.get_renewal_franchisee_details()
|
||||
@@ -344,6 +424,10 @@ class RenewalToDo:
|
||||
data_NGV['60天自动流转时间'] = data_NGV['过期日'] - pd.Timedelta(days=30)
|
||||
data_NGV['30天自动流转时间'] = data_NGV['过期日'] - pd.Timedelta(days=0)
|
||||
data_NGV['0天自动流转时间'] = data_NGV['过期日'] + pd.Timedelta(days=90)
|
||||
|
||||
data_NGV['120天是否跟进'] = "主动"
|
||||
data_NGV['60天是否跟进'] = "主动"
|
||||
data_NGV['30天是否跟进'] = "主动"
|
||||
# 格式化为字符串(去掉时区)
|
||||
for col in ['过期日', '120天自动流转时间', '60天自动流转时间', '30天自动流转时间', '0天自动流转时间']:
|
||||
data_NGV[col] = data_NGV[col].dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
@@ -356,24 +440,39 @@ class RenewalToDo:
|
||||
)
|
||||
|
||||
# 新增上次购买价格列
|
||||
# 1. 清洗并拼接类型+价格
|
||||
df_lp = self.last_price[['门店编码', '类型', '价格']].copy()
|
||||
# 1. 清洗数据
|
||||
df_lp = self.last_price[['门店编码', '类型', '订单商品名称', '价格']].copy()
|
||||
|
||||
# 处理“类型”和“订单商品名称”的缺失值
|
||||
df_lp['类型'] = df_lp['类型'].fillna('').astype(str)
|
||||
df_lp['订单商品名称'] = df_lp['订单商品名称'].fillna('').astype(str)
|
||||
|
||||
# 处理价格:转数字、四舍五入、填0、转字符串
|
||||
df_lp['价格'] = (
|
||||
pd.to_numeric(df_lp['价格'], errors='coerce')
|
||||
.round().fillna(0).astype(int).astype(str)
|
||||
)
|
||||
df_lp['类型_价格'] = df_lp['类型'] + df_lp['价格']
|
||||
|
||||
# 2. 按门店聚合,分号连接
|
||||
agg_df = df_lp.groupby('门店编码', as_index=False)['类型_价格'].apply(';'.join)
|
||||
# 2. 拼接“类型:价格”
|
||||
df_lp['类型_价格'] = df_lp['类型'] + ':' + df_lp['价格']
|
||||
|
||||
# 3. 合并回主表
|
||||
data_NGV = data_NGV.merge(agg_df, on='门店编码', how='left').fillna({'类型_价格': ''})
|
||||
data_NGV.rename(columns={'类型_价格': '上次购买价格'}, inplace=True)
|
||||
# 3. 按门店聚合两列
|
||||
agg_df = df_lp.groupby('门店编码', as_index=False).agg({
|
||||
'类型_价格': lambda x: ';'.join(x),
|
||||
'订单商品名称': lambda x: ';'.join(x)
|
||||
})
|
||||
|
||||
# 4. 处理没有匹配记录的门店(填空或默认值)
|
||||
data_NGV['上次购买价格'] = data_NGV['上次购买价格'].fillna('')
|
||||
# 4. 合并回主表
|
||||
data_NGV = data_NGV.merge(agg_df, on='门店编码', how='left')
|
||||
|
||||
# 5. 填充缺失值为空字符串,并重命名列
|
||||
data_NGV['类型_价格'] = data_NGV['类型_价格'].fillna('')
|
||||
data_NGV['订单商品名称'] = data_NGV['订单商品名称'].fillna('')
|
||||
|
||||
data_NGV.rename(columns={
|
||||
'类型_价格': '上次购买价格',
|
||||
'订单商品名称': '订单商品名称'
|
||||
}, inplace=True)
|
||||
|
||||
# 成员字段替换(现在列名是中文)
|
||||
staff_name_cols = [
|
||||
@@ -482,7 +581,7 @@ class RenewalToDo:
|
||||
|
||||
payload = {
|
||||
"api_key": "675b900991ad2491c69389ca",
|
||||
"entry_id": "6931063d64187eaf6b927557",
|
||||
"entry_id": "6965eec36b73376aa0b5bff8",
|
||||
"data_list": records
|
||||
}
|
||||
print(payload)
|
||||
@@ -502,11 +601,8 @@ class RenewalToDo:
|
||||
data_NGV = self.process_data()
|
||||
# step3:数据派发
|
||||
self.dispatch_task(data_NGV)
|
||||
# step4:过期日发生变化更新已有表单
|
||||
|
||||
# step5:自动同意原表单
|
||||
|
||||
common_module.send_task_status(task_start_time, "续约回访待办")
|
||||
# common_module.send_task_status(task_start_time, "续约回访待办")
|
||||
except Exception as e:
|
||||
error_task_logger.error(f"续约回访待办发生错误{e}")
|
||||
# common_module.send_task_error(task_start_time, "续约回访待办", str(e))
|
||||
|
||||
Reference in New Issue
Block a user