NGV换源

This commit is contained in:
2026-01-14 15:13:44 +08:00
parent 1ef81def0f
commit 25795f4a2d
9 changed files with 1964 additions and 66 deletions
+114 -18
View File
@@ -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))