From b37987e845ac64c2771d13dc25f19a86af469b41 Mon Sep 17 00:00:00 2001 From: wuaho Date: Thu, 4 Nov 2021 16:36:15 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=95=99=E5=AD=98=E5=92=8Clt?= =?UTF-8?q?v?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api_v1/endpoints/data_mana.py | 72 ++++++++++++++++++++++++++++++- api/api_v1/endpoints/query.py | 10 ++++- crud/__init__.py | 3 +- crud/select_map.py | 30 +++++++++++++ models/behavior_analysis.py | 2 +- models/x_analysis.py | 2 +- schemas/__init__.py | 3 +- schemas/select_map.py | 13 ++++++ 8 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 crud/select_map.py create mode 100644 schemas/select_map.py diff --git a/api/api_v1/endpoints/data_mana.py b/api/api_v1/endpoints/data_mana.py index 6f13057..b8523de 100644 --- a/api/api_v1/endpoints/data_mana.py +++ b/api/api_v1/endpoints/data_mana.py @@ -1,8 +1,9 @@ import json from aioredis import Redis -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, File from motor.motor_asyncio import AsyncIOMotorDatabase +import pandas as pd import crud, schemas @@ -31,7 +32,7 @@ async def read_data_attr( data = json.loads(data) res = [] - data_attr = await crud.data_attr.find_many(db, {'game':game, 'cat':cat}) + data_attr = await crud.data_attr.find_many(db, {'game': game, 'cat': cat}) data_attr = {item['name']: item for item in data_attr} for k, v in data.items(): @@ -61,3 +62,70 @@ async def edit_data_attr( return schemas.Msg(code=0, msg='ok', data=data_in) +# +# @router.post("/add_select_map") +# async def add_map( +# request: Request, +# game: str, +# data_in: schemas.SelectMap, +# db: AsyncIOMotorDatabase = Depends(get_database), +# current_user: schemas.UserDB = Depends(deps.get_current_user) +# ) -> schemas.Msg: +# """添加属性值选择映射""" +# +# """ +# { +# game:aaa, +# attr_name:bbb, +# map_:{ +# '区服aa':'1', +# '区服vvv':'5', +# } +# +# } +# """ +# await crud.select_map.save(db, data_in) +# return schemas.Msg(code=0, msg='ok', data=data_in) + + +@router.post("/add_select_map") +async def add_select_map( + request: Request, + game: str, + file: bytes = File(...), + db: AsyncIOMotorDatabase = Depends(get_database), + current_user: schemas.UserDB = Depends(deps.get_current_user) +) -> schemas.Msg: + """添加属性值选择映射""" + dfs = pd.read_excel(file, engine='openpyxl', sheet_name=None) + for attr_name, df in dfs.items(): + map_ = df.to_dict('records') + data_in = schemas.SelectMap(game=game, attr_name=attr_name, map_=map_) + await crud.select_map.save(db, data_in) + return schemas.Msg(code=0, msg='ok', data=1) + + +@router.get("/select_list") +async def select_list( + request: Request, + game: str, + db: AsyncIOMotorDatabase = Depends(get_database), + current_user: schemas.UserDB = Depends(deps.get_current_user) +) -> schemas.Msg: + """属性值选择映射列表""" + resp = await crud.select_map.get_list(db, game) + return schemas.Msg(code=0, msg='ok', data=resp) + + +@router.post("/select_attr") +async def select_attr( + request: Request, + game: str, + data_in: schemas.SelectAttr, + db: AsyncIOMotorDatabase = Depends(get_database), + current_user: schemas.UserDB = Depends(deps.get_current_user) +) -> schemas.Msg: + """属性值选择映射""" + resp = await crud.select_map.get_select(db, data_in, game) + return schemas.Msg(code=0, msg='ok', data=resp) + diff --git a/api/api_v1/endpoints/query.py b/api/api_v1/endpoints/query.py index 1844886..47ffc30 100644 --- a/api/api_v1/endpoints/query.py +++ b/api/api_v1/endpoints/query.py @@ -329,7 +329,7 @@ async def retention_model(request: Request, n = (pd.Timestamp.now().date() - date).days if i > n: continue - 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}'] avgo[i] = avgo.setdefault(i, 0) + v[f'on{i}'] tmp['p'].append(v[f'p{i}']) @@ -343,7 +343,13 @@ async def retention_model(request: Request, tmp['p_outflow'] = (pd.Series(avgo) * 100 / tmp['d0']).round(2).tolist() tmp['n_outflow'] = pd.Series(avgo).values.tolist() - title = ['日期', '用户数', '次留', *[f'{i}留' for i in retention_n[1:] if i <= max_retention_n]] + title = ['日期', '用户数', '次留', *[f'{i}留' 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, diff --git a/crud/__init__.py b/crud/__init__.py index a66d533..2cef920 100644 --- a/crud/__init__.py +++ b/crud/__init__.py @@ -12,4 +12,5 @@ from .crud_event_mana import event_mana from .crud_api_list import api_list from .crud_role import role from .crud_check_data import check_data -from .user_label import user_label \ No newline at end of file +from .user_label import user_label +from .select_map import select_map \ No newline at end of file diff --git a/crud/select_map.py b/crud/select_map.py new file mode 100644 index 0000000..58e27da --- /dev/null +++ b/crud/select_map.py @@ -0,0 +1,30 @@ +from motor.motor_asyncio import AsyncIOMotorDatabase + +import schemas +from crud.base import CRUDBase + +__all__ = 'select_map', + + +class CRUDSelectMap(CRUDBase): + async def save(self, db: AsyncIOMotorDatabase, data_in: schemas.SelectMap): + where = {'attr_name': data_in.attr_name, 'game': data_in.game} + return await self.update_one(db, where, {'$set': data_in.dict(skip_defaults=True)}, upsert=True) + + # async def read(self, db: AsyncIOMotorDatabase, data_in: schemas.SelectMap): + # where = data_in.dict(skip_defaults=True) + # res = await self.find_many(db, where) + # return res + # + async def get_list(self, db: AsyncIOMotorDatabase, game: str): + where = {'game': game} + res = await self.find_many(db, where, {'_id': 0}) + return res + + async def get_select(self, db: AsyncIOMotorDatabase, data_in: schemas.SelectAttr, game: str): + where = {'game': game, **data_in.dict()} + res = await self.find_one(db, where, {'_id': 0}) + return res + + +select_map = CRUDSelectMap('select_map') diff --git a/models/behavior_analysis.py b/models/behavior_analysis.py index a1f4edc..eab67f6 100644 --- a/models/behavior_analysis.py +++ b/models/behavior_analysis.py @@ -771,7 +771,7 @@ ORDER BY values desc""" days = (arrow.get(self.end_date).date() - arrow.get(self.start_date).date()).days keep = [] cnt = [] - retention_n = [*[k for k in range(1, 31)], 45, 60, 90, 120, 180, 240, 300, 360] + retention_n = [*[k for k in range(1, 61)], 90, 120, 180, 240, 300, 360] """ cnt0-cnt1 as on1, diff --git a/models/x_analysis.py b/models/x_analysis.py index 63a1c0b..fd94901 100644 --- a/models/x_analysis.py +++ b/models/x_analysis.py @@ -132,7 +132,7 @@ class XAnalysis: sumpay = [] sum_money = [] # for i in range(1, days + 2): - ltv_n = [*[k for k in range(1, 31)], 45, 60, 90, 120, 180, 240, 300, 360] + ltv_n = [*[k for k in range(1, 61)], 90, 120, 180, 240, 300, 360] for i in ltv_n: # select_ltv.append(func.round(sa.Column(f'sumpay_{i}') / sa.Column('cnt1'), 2).label(f'LTV{i}')) select_ltv.append( diff --git a/schemas/__init__.py b/schemas/__init__.py index d47a4fe..61f46a7 100644 --- a/schemas/__init__.py +++ b/schemas/__init__.py @@ -16,4 +16,5 @@ from .xquery import * from .api_list import * from .role import * from .check_data import * -from .userlabel import * \ No newline at end of file +from .userlabel import * +from .select_map import * \ No newline at end of file diff --git a/schemas/select_map.py b/schemas/select_map.py new file mode 100644 index 0000000..c064b8a --- /dev/null +++ b/schemas/select_map.py @@ -0,0 +1,13 @@ +from typing import Any, List, Union, Dict + +from pydantic import BaseModel, Field + + +class SelectMap(BaseModel): + game: str + attr_name: str + map_: List[Dict] + + +class SelectAttr(BaseModel): + attr_name: str