增加LTV全局筛选功能
This commit is contained in:
parent
529bf55d37
commit
713ed2d7e2
@ -5,7 +5,6 @@ from motor.motor_asyncio import AsyncIOMotorDatabase
|
|||||||
import crud, schemas
|
import crud, schemas
|
||||||
from api import deps
|
from api import deps
|
||||||
from core.config import settings
|
from core.config import settings
|
||||||
|
|
||||||
from db import get_database
|
from db import get_database
|
||||||
from db.ckdb import CKDrive, get_ck_db
|
from db.ckdb import CKDrive, get_ck_db
|
||||||
from schemas.project import ProjectCreate
|
from schemas.project import ProjectCreate
|
||||||
@ -25,6 +24,7 @@ async def create(
|
|||||||
"""创建项目"""
|
"""创建项目"""
|
||||||
try:
|
try:
|
||||||
res_project = await crud.project.create(db, data_in, current_user=request.user)
|
res_project = await crud.project.create(db, data_in, current_user=request.user)
|
||||||
|
await crud.project_number.createxiangmu(db, data_in)
|
||||||
except pymongo.errors.DuplicateKeyError:
|
except pymongo.errors.DuplicateKeyError:
|
||||||
return schemas.Msg(code=-1, msg='项目名已存在', data='项目名已存在')
|
return schemas.Msg(code=-1, msg='项目名已存在', data='项目名已存在')
|
||||||
|
|
||||||
@ -74,8 +74,28 @@ async def read_project(request: Request,
|
|||||||
resp = await crud.project.get_my_game(db, game_list)
|
resp = await crud.project.get_my_game(db, game_list)
|
||||||
|
|
||||||
return schemas.Msg(code=0, msg='ok', data=resp)
|
return schemas.Msg(code=0, msg='ok', data=resp)
|
||||||
|
#获取项目名和渠道名project_name
|
||||||
|
@router.get("/project_name")
|
||||||
|
async def project_name(request: Request,
|
||||||
|
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||||
|
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||||
|
):
|
||||||
|
if request.user.username == 'root':
|
||||||
|
res = await crud.project_number.all_xiangmu(db)
|
||||||
|
for i in res:
|
||||||
|
i['_id'] = str(i['_id'])
|
||||||
|
return schemas.Msg(code=0,msg='ok',data=res)
|
||||||
|
#添加项目名,渠道名
|
||||||
|
@router.post("/add_project_name")
|
||||||
|
async def add_project_name(request: Request,
|
||||||
|
data_in: schemas.ProjectnumberInsert,
|
||||||
|
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||||
|
current_user: schemas.UserDB = Depends(deps.get_current_user)):
|
||||||
|
#插入数据
|
||||||
|
#await crud.project_number.create(db, data_in)
|
||||||
|
#修改数据
|
||||||
|
await crud.project_number.update(db, data_in)
|
||||||
|
return schemas.Msg(code=0, msg='修改成功', data=True)
|
||||||
@router.get("/detail")
|
@router.get("/detail")
|
||||||
async def detail(request: Request,
|
async def detail(request: Request,
|
||||||
game: str,
|
game: str,
|
||||||
|
@ -321,6 +321,112 @@ async def retention_model(request: Request,
|
|||||||
for d in set(res['date_range']) - set(df.index):
|
for d in set(res['date_range']) - set(df.index):
|
||||||
df.loc[d] = 0
|
df.loc[d] = 0
|
||||||
|
|
||||||
|
df.sort_index(inplace=True)
|
||||||
|
summary_values = {'均值': {}}
|
||||||
|
max_retention_n = 1
|
||||||
|
#留存人数
|
||||||
|
avg = {}
|
||||||
|
#流失人数
|
||||||
|
avgo = {}
|
||||||
|
for date, v in df.T.items():
|
||||||
|
#字典中data存在时不替换,否则将data替换成空字典
|
||||||
|
tmp = summary_values.setdefault(date, dict())
|
||||||
|
tmp['d0'] = int(v.cnt0)
|
||||||
|
tmp['p'] = []
|
||||||
|
tmp['n'] = []
|
||||||
|
tmp['p_outflow'] = []
|
||||||
|
tmp['n_outflow'] = []
|
||||||
|
for i in retention_n:
|
||||||
|
n = (pd.Timestamp.now().date() - date).days
|
||||||
|
if i > n:
|
||||||
|
continue
|
||||||
|
# max_retention_n = i if i > max_retention_n else max_retention_n
|
||||||
|
#留存的人数
|
||||||
|
avg[i] = avg.setdefault(i, 0) + v[f'cnt{i}']
|
||||||
|
#流失的人数
|
||||||
|
avgo[i] = avgo.setdefault(i, 0) + v[f'on{i}']
|
||||||
|
tmp['p'].append(v[f'p{i}'])
|
||||||
|
tmp['n'].append(v[f'cnt{i}'])
|
||||||
|
tmp['p_outflow'].append(v[f'op{i}'])
|
||||||
|
tmp['n_outflow'].append(v[f'on{i}'])
|
||||||
|
tmp = summary_values['均值']
|
||||||
|
retention_avg_dict = {}
|
||||||
|
|
||||||
|
for rn in retention_n:
|
||||||
|
for rt, rd in df.T.items():
|
||||||
|
if rt + datetime.timedelta(days=rn) <= pd.datetime.now().date():
|
||||||
|
retention_avg_dict.setdefault(rn, {'cnt0': 0, 'cntn': 0,'o_cnt0':0,'o_cntn':0})
|
||||||
|
retention_avg_dict[rn]['cnt0'] += rd['cnt0']
|
||||||
|
retention_avg_dict[rn]['cntn'] += rd[f'cnt{rn}']
|
||||||
|
retention_avg_dict[rn]['o_cnt0'] += rd['cnt0']
|
||||||
|
retention_avg_dict[rn]['o_cntn'] += rd[f'on{rn}']
|
||||||
|
|
||||||
|
tmp['p'] = []
|
||||||
|
tmp['n'] = []
|
||||||
|
tmp['p_outflow'] = []
|
||||||
|
tmp['n_outflow'] = []
|
||||||
|
tmp['d0'] = 0
|
||||||
|
for rt, rd in retention_avg_dict.items():
|
||||||
|
tmp['d0'] = int(df['cnt0'].sum())
|
||||||
|
n = round(rd['cntn'] * 100 / rd['cnt0'],2)
|
||||||
|
n = 0 if np.isnan(n) else n
|
||||||
|
tmp['p'].append(n)
|
||||||
|
tmp['n'].append(rd['cntn'])
|
||||||
|
n = round(rd['o_cntn'] * 100 / rd['cnt0'],2)
|
||||||
|
n = 0 if np.isnan(n) else n
|
||||||
|
tmp['p_outflow'].append(n)
|
||||||
|
tmp['n_outflow'].append(rd['o_cntn'])
|
||||||
|
|
||||||
|
#次留数
|
||||||
|
title = ['日期', '用户数', '次留', *[f'{i + 1}留' for i in retention_n[1:]]]
|
||||||
|
|
||||||
|
# 未到达的日期需要补齐-
|
||||||
|
retention_length = len(retention_n)
|
||||||
|
for _, items in summary_values.items():
|
||||||
|
for key in ['p', 'n', 'p_outflow', 'n_outflow']:
|
||||||
|
items[key].extend(['-'] * (retention_length - len(items[key])))
|
||||||
|
|
||||||
|
resp = {
|
||||||
|
'summary_values': summary_values,
|
||||||
|
# 'values': values,
|
||||||
|
'date_range': [d.strftime('%Y-%m-%d') for d in date_range],
|
||||||
|
'title': title,
|
||||||
|
'filter_item_type': filter_item_type,
|
||||||
|
'filter_item': filter_item,
|
||||||
|
'start_date': res['start_date'],
|
||||||
|
'end_date': res['end_date'],
|
||||||
|
'time_particle': res['time_particle']
|
||||||
|
|
||||||
|
}
|
||||||
|
return schemas.Msg(code=0, msg='ok', data=resp)
|
||||||
|
|
||||||
|
#计算流失率
|
||||||
|
# retention_model
|
||||||
|
# retention_model_loss
|
||||||
|
#@router.post("/retention_model")
|
||||||
|
async def retention_model01(request: Request,
|
||||||
|
game: str,
|
||||||
|
ckdb: CKDrive = Depends(get_ck_db),
|
||||||
|
db: AsyncIOMotorDatabase = Depends(get_database),
|
||||||
|
analysis: BehaviorAnalysis = Depends(BehaviorAnalysis),
|
||||||
|
current_user: schemas.UserDB = Depends(deps.get_current_user)
|
||||||
|
) -> schemas.Msg:
|
||||||
|
await analysis.init(data_where=current_user.data_where)
|
||||||
|
res = await analysis.retention_model_sql2() #初始化开始时间结束时间,sql语句 字典
|
||||||
|
sql = res['sql'] #获取到sql语句
|
||||||
|
df = await ckdb.query_dataframe(sql)
|
||||||
|
if df.empty:
|
||||||
|
return schemas.Msg(code=-9, msg='无数据', data=None)
|
||||||
|
|
||||||
|
date_range = res['date_range'] #时间 列表
|
||||||
|
unit_num = res['unit_num'] #int
|
||||||
|
retention_n = res['retention_n'] #列表 int
|
||||||
|
filter_item_type = res['filter_item_type'] #all
|
||||||
|
filter_item = res['filter_item'] #列表 0,1,3,7,14,21,30
|
||||||
|
df.set_index('reg_date', inplace=True)
|
||||||
|
for d in set(res['date_range']) - set(df.index):
|
||||||
|
df.loc[d] = 0
|
||||||
|
|
||||||
df.sort_index(inplace=True)
|
df.sort_index(inplace=True)
|
||||||
summary_values = {'均值': {}}
|
summary_values = {'均值': {}}
|
||||||
max_retention_n = 1
|
max_retention_n = 1
|
||||||
@ -341,7 +447,8 @@ async def retention_model(request: Request,
|
|||||||
# max_retention_n = i if i > max_retention_n else max_retention_n
|
# max_retention_n = i if i > max_retention_n else max_retention_n
|
||||||
avg[i] = avg.setdefault(i, 0) + v[f'cnt{i}']
|
avg[i] = avg.setdefault(i, 0) + v[f'cnt{i}']
|
||||||
avgo[i] = avgo.setdefault(i, 0) + v[f'on{i}']
|
avgo[i] = avgo.setdefault(i, 0) + v[f'on{i}']
|
||||||
tmp['p'].append(v[f'p{i}'])
|
tmp['p'].append(round(100-v[f'p{i}'],2))
|
||||||
|
#tmp['p'].append(v[f'p{i}'])
|
||||||
tmp['n'].append(v[f'cnt{i}'])
|
tmp['n'].append(v[f'cnt{i}'])
|
||||||
tmp['p_outflow'].append(v[f'op{i}'])
|
tmp['p_outflow'].append(v[f'op{i}'])
|
||||||
tmp['n_outflow'].append(v[f'on{i}'])
|
tmp['n_outflow'].append(v[f'on{i}'])
|
||||||
@ -365,7 +472,8 @@ async def retention_model(request: Request,
|
|||||||
tmp['d0'] = 0
|
tmp['d0'] = 0
|
||||||
for rt, rd in retention_avg_dict.items():
|
for rt, rd in retention_avg_dict.items():
|
||||||
tmp['d0'] = int(df['cnt0'].sum())
|
tmp['d0'] = int(df['cnt0'].sum())
|
||||||
n = round(rd['cntn'] * 100 / rd['cnt0'],2)
|
n = round(100-(rd['cntn'] * 100 / rd['cnt0']), 2)
|
||||||
|
#n = round(rd['cntn'] * 100 / rd['cnt0'],2)
|
||||||
n = 0 if np.isnan(n) else n
|
n = 0 if np.isnan(n) else n
|
||||||
tmp['p'].append(n)
|
tmp['p'].append(n)
|
||||||
tmp['n'].append(rd['cntn'])
|
tmp['n'].append(rd['cntn'])
|
||||||
@ -375,7 +483,7 @@ async def retention_model(request: Request,
|
|||||||
tmp['n_outflow'].append(rd['o_cntn'])
|
tmp['n_outflow'].append(rd['o_cntn'])
|
||||||
|
|
||||||
|
|
||||||
title = ['日期', '用户数', '次留', *[f'{i + 1}留' for i in retention_n[1:]]]
|
title = ['日期', '用户数', '次流失', *[f'{i + 1}流失' for i in retention_n[1:]]]
|
||||||
|
|
||||||
# 未到达的日期需要补齐-
|
# 未到达的日期需要补齐-
|
||||||
retention_length = len(retention_n)
|
retention_length = len(retention_n)
|
||||||
@ -398,6 +506,7 @@ async def retention_model(request: Request,
|
|||||||
return schemas.Msg(code=0, msg='ok', data=resp)
|
return schemas.Msg(code=0, msg='ok', data=resp)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/retention_model_export")
|
@router.post("/retention_model_export")
|
||||||
async def retention_model_export(request: Request,
|
async def retention_model_export(request: Request,
|
||||||
game: str,
|
game: str,
|
||||||
@ -899,7 +1008,7 @@ async def scatter_model(
|
|||||||
for i in labels:
|
for i in labels:
|
||||||
v +=1
|
v +=1
|
||||||
if int(i) == 1:
|
if int(i) == 1:
|
||||||
labels_dict01["1"]=labels_dict["1"]
|
labels_dict01["1"]=labels_dict['1']
|
||||||
else:
|
else:
|
||||||
# for number in labels_dict.keys():
|
# for number in labels_dict.keys():
|
||||||
# if number >=i:
|
# if number >=i:
|
||||||
|
@ -22,7 +22,7 @@ from db.redisdb import get_redis_pool, RedisDrive
|
|||||||
from models.behavior_analysis import BehaviorAnalysis
|
from models.behavior_analysis import BehaviorAnalysis
|
||||||
from models.user_analysis import UserAnalysis
|
from models.user_analysis import UserAnalysis
|
||||||
from models.x_analysis import XAnalysis
|
from models.x_analysis import XAnalysis
|
||||||
from utils import DfToStream
|
from utils import DfToStream, get_bijiao
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@ -50,12 +50,35 @@ async def ltv_model_sql(
|
|||||||
) -> schemas.Msg:
|
) -> schemas.Msg:
|
||||||
""" ltv模型sql """
|
""" ltv模型sql """
|
||||||
await analysis.init(data_where=current_user.data_where)
|
await analysis.init(data_where=current_user.data_where)
|
||||||
|
|
||||||
res = analysis.ltv_model_sql()
|
res = analysis.ltv_model_sql()
|
||||||
sql = res['sql']
|
sql = res['sql']
|
||||||
|
#仅一条筛选条件则是把GM过滤后获取全部数据
|
||||||
|
if len(analysis.global_filters)==1 and analysis.global_filters[0]['strftv']=='GM':
|
||||||
|
df = await ckdb.query_dataframe(sql)
|
||||||
|
#多条筛选条件则合成新的sql
|
||||||
|
else:
|
||||||
|
new_sql=""""""
|
||||||
|
#拆分sql
|
||||||
|
split_sql = sql.split('AND 1')
|
||||||
|
#获取每一条筛选条件
|
||||||
|
for i in analysis.global_filters:
|
||||||
|
#剔除GM
|
||||||
|
if i['strftv'] != 'GM':
|
||||||
|
#获取筛选条件的包含关系
|
||||||
|
bijiao=get_bijiao(i["comparator"])
|
||||||
|
#获取筛选条件的值
|
||||||
|
condition=tuple(i['ftv'])
|
||||||
|
#获取事件名
|
||||||
|
columnName=i['columnName']
|
||||||
|
dd = f""" AND {game}.event.{columnName} {bijiao} {condition}"""
|
||||||
|
new_sql+=dd
|
||||||
|
split_="""AND 1 """
|
||||||
|
news_sql = split_sql[0] + split_+new_sql + split_sql[1] + split_+new_sql+ split_sql[2]+split_+split_sql[3]
|
||||||
|
df = await ckdb.query_dataframe(news_sql)
|
||||||
|
|
||||||
quota = res['quota'] #字段名
|
quota = res['quota'] #字段名
|
||||||
ltv_n = res['ltv_n']
|
ltv_n = res['ltv_n']
|
||||||
df = await ckdb.query_dataframe(sql)
|
#df = await ckdb.query_dataframe(sql)
|
||||||
if df.empty:
|
if df.empty:
|
||||||
return schemas.Msg(code=-9, msg='查无数据')
|
return schemas.Msg(code=-9, msg='查无数据')
|
||||||
df.fillna(0, inplace=True) #修改原对象,以0填补空缺值
|
df.fillna(0, inplace=True) #修改原对象,以0填补空缺值
|
||||||
@ -70,7 +93,7 @@ async def ltv_model_sql(
|
|||||||
# df.sort_values('date', inplace=True) # 根据date进行倒叙排序
|
# df.sort_values('date', inplace=True) # 根据date进行倒叙排序
|
||||||
|
|
||||||
for d in set(res['date_range']) - set(df['date']):
|
for d in set(res['date_range']) - set(df['date']):
|
||||||
#在有效日期最后一行补充行数据(值都为0),补充的行数为两个集合的差集长度
|
#在有效日期最后一行补充行数据(值都为'-'),补充的行数为两个集合的差集长度
|
||||||
df.loc[len(df)] = '-'
|
df.loc[len(df)] = '-'
|
||||||
#在date此列补充多行数据(值为两个集合差集的子元素)
|
#在date此列补充多行数据(值为两个集合差集的子元素)
|
||||||
df.loc[len(df) - 1, 'date'] = d
|
df.loc[len(df) - 1, 'date'] = d
|
||||||
@ -90,9 +113,16 @@ async def ltv_model_sql(
|
|||||||
df2 = df[['注册日期', cat, *[f'sumpay_{i}' for i in ltv_n]]]
|
df2 = df[['注册日期', cat, *[f'sumpay_{i}' for i in ltv_n]]]
|
||||||
df2.replace('-', 0, inplace=True) #True改变原数据,前面是需要替换的值,后面是替换后的值。 在原数据把下划线替换成0
|
df2.replace('-', 0, inplace=True) #True改变原数据,前面是需要替换的值,后面是替换后的值。 在原数据把下划线替换成0
|
||||||
#修改下面代码
|
#修改下面代码
|
||||||
|
# 去除sumpay_1的值为0的列
|
||||||
|
new_df2 = (df2.drop(df2[(df2.sumpay_2 == 0)].index))
|
||||||
|
#为new_df2排序
|
||||||
|
new_df2=new_df2.reset_index(drop=True)
|
||||||
#求相差天数
|
#求相差天数
|
||||||
str_time = str(res['date_range'][0])
|
str_time =new_df2['注册日期'][0]
|
||||||
split_time = str_time.split('-')
|
str_time01=str(str_time)
|
||||||
|
split_time = str_time01.split('-')
|
||||||
|
#str_time = str(res['date_range'][0])
|
||||||
|
# split_time = str_time.split('-')
|
||||||
now_time = time.strftime("%Y-%m-%d", time.localtime())
|
now_time = time.strftime("%Y-%m-%d", time.localtime())
|
||||||
split_now_time = now_time.split('-')
|
split_now_time = now_time.split('-')
|
||||||
today = datetime.datetime(int(split_time[0]), int(split_time[1]), int(split_time[2]))
|
today = datetime.datetime(int(split_time[0]), int(split_time[1]), int(split_time[2]))
|
||||||
@ -102,14 +132,26 @@ async def ltv_model_sql(
|
|||||||
_listData = {}
|
_listData = {}
|
||||||
for i in ltv_n:
|
for i in ltv_n:
|
||||||
if i <=newday:
|
if i <=newday:
|
||||||
|
#计算均值
|
||||||
|
#avgLtv = (new_df2[[f'sumpay_{i}']][0:newday + 1 - i].sum() / new_df2[cat][0:newday + 1 - i].sum()).round(2)
|
||||||
|
#12.20号计算LTV均值的时候分母包括当天未充值新增设备数,比剔除掉的计算值偏小
|
||||||
avgLtv = (df2[[f'sumpay_{i}']][0:newday + 1 - i].sum() / df2[cat][0:newday + 1 - i].sum()).round(2)
|
avgLtv = (df2[[f'sumpay_{i}']][0:newday + 1 - i].sum() / df2[cat][0:newday + 1 - i].sum()).round(2)
|
||||||
|
#取出均值
|
||||||
new_avgLtv=str(avgLtv).split('\n')[0].split(' ')
|
new_avgLtv=str(avgLtv).split('\n')[0].split(' ')
|
||||||
new_avgLtv01=new_avgLtv[len(new_avgLtv)-1]
|
new_avgLtv01=new_avgLtv[len(new_avgLtv)-1]
|
||||||
if new_avgLtv01 == 'NaN':
|
if new_avgLtv01 == 'NaN':
|
||||||
_listData[f'sumpay_{i}'] = '-'
|
_listData[f'sumpay_{i}'] = '-'
|
||||||
else:
|
else:
|
||||||
_listData[f'sumpay_{i}'] = new_avgLtv01
|
_listData[f'sumpay_{i}'] = new_avgLtv01
|
||||||
|
|
||||||
|
#原代码
|
||||||
|
# avgLtv=(df2[[f'sumpay_{i}']][0:newday+1-i].sum()/df2[cat][0:newday+1-i].sum()).round(2)
|
||||||
|
# new_avgLtv=str(avgLtv).split('\n')[0].split(' ')
|
||||||
|
# new_avgLtv01=new_avgLtv[len(new_avgLtv)-1]
|
||||||
|
# if new_avgLtv01 == 'NaN':
|
||||||
|
# _listData[f'sumpay_{i}'] = '-'
|
||||||
|
# else:
|
||||||
|
# _listData[f'sumpay_{i}'] = new_avgLtv01
|
||||||
else:
|
else:
|
||||||
_listData[f'sumpay_{i}']='-'
|
_listData[f'sumpay_{i}']='-'
|
||||||
avgLtvlist = pd.Series(_listData)
|
avgLtvlist = pd.Series(_listData)
|
||||||
@ -117,12 +159,16 @@ async def ltv_model_sql(
|
|||||||
_listname=[]
|
_listname=[]
|
||||||
#计算总累计LTV最后一个值
|
#计算总累计LTV最后一个值
|
||||||
for k, v in _listData.items():
|
for k, v in _listData.items():
|
||||||
if v !=0:
|
if v != 0 or v!= '-':
|
||||||
|
# if v !=0:
|
||||||
_listname.append(k)
|
_listname.append(k)
|
||||||
max_nmu=max(_listname)
|
max_nmu=max(_listname)
|
||||||
|
#max_num = (new_df2[[max_nmu]].sum() / new_df2[cat].sum()).round(2)
|
||||||
max_num=(df2[[max_nmu]].sum()/df2[cat].sum()).round(2)
|
max_num=(df2[[max_nmu]].sum()/df2[cat].sum()).round(2)
|
||||||
max_number=str(max_num[0])
|
max_number=str(max_num[0])
|
||||||
df1.loc[len(df1)] = ['均值', df2[cat].sum(), *avgLtvlist]
|
df1.loc[len(df1)] = ['均值', df2[cat].sum(), *avgLtvlist]
|
||||||
|
#原代码
|
||||||
|
#df1.loc[len(df1)] = ['均值', df2[cat].sum(), *avgLtvlist]
|
||||||
|
|
||||||
# avg_ltv = (df2[[f'sumpay_{i}' for i in ltv_n]].sum() / df2[cat].sum()).round(2)
|
# avg_ltv = (df2[[f'sumpay_{i}' for i in ltv_n]].sum() / df2[cat].sum()).round(2)
|
||||||
#df1.loc[len(df1)] = ['均值', df2[cat].sum(), *avg_ltv]
|
#df1.loc[len(df1)] = ['均值', df2[cat].sum(), *avg_ltv]
|
||||||
@ -141,9 +187,10 @@ async def ltv_model_sql(
|
|||||||
|
|
||||||
|
|
||||||
#把列中累计LTV等于0的值改成'-'
|
#把列中累计LTV等于0的值改成'-'
|
||||||
df1.loc[df1['累计LTV']==0, '累计LTV'] = '-'
|
#df1.loc[df1['累计LTV']==0, '累计LTV'] = '-'
|
||||||
#剔除行,列的累计LTV=='-'的剔除出去
|
#剔除行,列的累计LTV=='-'的剔除出去
|
||||||
df3 = df1.drop(df1[(df1.累计LTV=='-')].index)
|
df3 = df1.drop(df1[(df1.LTV1 == '-')].index)
|
||||||
|
#df3 = df1.drop(df1[(df1.累计LTV=='-')].index)
|
||||||
|
|
||||||
days = (pd.Timestamp.now().date() - pd.to_datetime(res['start_date']).date()).days
|
days = (pd.Timestamp.now().date() - pd.to_datetime(res['start_date']).date()).days
|
||||||
df1.iloc[len(df1) - 1, days + 4:] = '-'
|
df1.iloc[len(df1) - 1, days + 4:] = '-'
|
||||||
|
@ -14,3 +14,4 @@ from .crud_role import role
|
|||||||
from .crud_check_data import check_data
|
from .crud_check_data import check_data
|
||||||
from .user_label import user_label
|
from .user_label import user_label
|
||||||
from .select_map import select_map
|
from .select_map import select_map
|
||||||
|
from .crud_project_number import project_number
|
33
crud/crud_project_number.py
Normal file
33
crud/crud_project_number.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from motor.motor_asyncio import AsyncIOMotorDatabase
|
||||||
|
import schemas
|
||||||
|
from crud.base import CRUDBase
|
||||||
|
|
||||||
|
__all__ = 'project_number',
|
||||||
|
|
||||||
|
from utils import get_uid
|
||||||
|
|
||||||
|
|
||||||
|
class CRUDProjectNumber(CRUDBase):
|
||||||
|
# 获取所有数据
|
||||||
|
async def all_xiangmu(self, db: AsyncIOMotorDatabase):
|
||||||
|
return await self.find_many(db, {})
|
||||||
|
|
||||||
|
# 修改数据
|
||||||
|
async def update(self, db: AsyncIOMotorDatabase, data_in: schemas.AddProjectnumber):
|
||||||
|
game = data_in.game
|
||||||
|
add_ditch = []
|
||||||
|
for member in data_in.ditch:
|
||||||
|
add_ditch.append(member.dict())
|
||||||
|
await self.update_one(db, {'game': game}, {'$set': {'ditch': add_ditch}})
|
||||||
|
|
||||||
|
# 插入数据
|
||||||
|
async def create(self, db: AsyncIOMotorDatabase, data_in: schemas.ProjectnumberInsert):
|
||||||
|
# await self.update_one(db, {'xiangmu': data_in.xiangmu}, {'$set': data_in.dict()}, upsert=True)
|
||||||
|
await self.update_one(db, {data_in.game, data_in.ditch}, upsert=True)
|
||||||
|
|
||||||
|
# 同步插入项目
|
||||||
|
async def createxiangmu(self, db: AsyncIOMotorDatabase, data_in: schemas.ProjectnumberInsert):
|
||||||
|
await self.insert_one(db, data_in.dict())
|
||||||
|
|
||||||
|
|
||||||
|
project_number = CRUDProjectNumber('project_number')
|
@ -18,3 +18,4 @@ from .role import *
|
|||||||
from .check_data import *
|
from .check_data import *
|
||||||
from .userlabel import *
|
from .userlabel import *
|
||||||
from .select_map import *
|
from .select_map import *
|
||||||
|
from .project_number import *
|
@ -51,7 +51,7 @@ class ProjectDelMember(BaseModel):
|
|||||||
class ProjectCreate(ProjectBase):
|
class ProjectCreate(ProjectBase):
|
||||||
name: str = Field(..., title='项目名')
|
name: str = Field(..., title='项目名')
|
||||||
game: str = Field(..., title='游戏代号')
|
game: str = Field(..., title='游戏代号')
|
||||||
|
#qudao:str = Field(...,title='渠道')
|
||||||
|
|
||||||
# 查询某个项目看板
|
# 查询某个项目看板
|
||||||
class ProjectKanban(DBBase):
|
class ProjectKanban(DBBase):
|
||||||
|
17
schemas/project_number.py
Normal file
17
schemas/project_number.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectnumberList(BaseModel):
|
||||||
|
main_channel: str
|
||||||
|
ditch: str
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectnumberInsert(BaseModel):
|
||||||
|
game: str
|
||||||
|
ditch: List[ProjectnumberList]
|
||||||
|
name: str
|
||||||
|
|
||||||
|
class AddProjectnumber(BaseModel):
|
||||||
|
game: str
|
||||||
|
ditch: List[ProjectnumberInsert]
|
@ -4,3 +4,11 @@ import time
|
|||||||
|
|
||||||
def get_uid():
|
def get_uid():
|
||||||
return hex(int(time.time() * 10 ** 7) + random.randint(0, 10000))[2:]
|
return hex(int(time.time() * 10 ** 7) + random.randint(0, 10000))[2:]
|
||||||
|
|
||||||
|
|
||||||
|
# 获取筛选条件的包含关系
|
||||||
|
def get_bijiao(bijiao):
|
||||||
|
if bijiao == '==' or bijiao == 'in' or bijiao == 'like' or bijiao == 'is not null':
|
||||||
|
return "IN"
|
||||||
|
elif bijiao == '!=' or bijiao == 'not like' or bijiao == 'is null':
|
||||||
|
return 'NOT LIKE'
|
||||||
|
Loading…
Reference in New Issue
Block a user