Commit 48ad50d8 authored by xianyang's avatar xianyang

月度统计接口

parent f0090492
from concurrent.futures.thread import ThreadPoolExecutor
from sqlalchemy.orm import Session
from app.api.export import schemas
from core.config.env import env
from libs.business import TYPE_NAME
from libs.db_link import LinkMysql
from libs.functions import get_now_datetime
from libs.orm import QueryAllData
from models.export import ExportFile
import pandas as pd
from starlette.responses import StreamingResponse
def get_export_list(db: Session, param):
......@@ -58,3 +64,76 @@ def create_export_data(db: Session, export, operator):
def get_source_data(db):
res = db.query(ExportFile.source).filter().group_by('source').all()
return [i[0] for i in res]
class CalculationMonthlyBill(object):
"""月度计算,出入账目"""
def __init__(self):
self.structure_list = []
self.structure_key = []
@staticmethod
def data_to_table(data):
"""数据导出"""
bk = pd.DataFrame(data)
with pd.ExcelWriter(f'static/业务类型月度汇总报表.xlsx') as writer:
bk.to_excel(writer, sheet_name='业务类型月度汇总', index=False)
file = open(writer, 'rb')
return StreamingResponse(file, media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
def month_statistics_task(self, date, page, size):
"""主函数"""
db = env.MysqlDB
db["database"] = env.DB_HISTORY
sql = f"SELECT reference_type, type, SUM(cast(amount as decimal(20,6)))/1000 as money FROM {date} GROUP BY reference_type, type ORDER BY reference_type"
res_data = LinkMysql(db).query_mysql(sql)
for res in res_data:
if res["reference_type"] in self.structure_key:
continue
if res["reference_type"] in TYPE_NAME:
name = TYPE_NAME[res["reference_type"]]
else:
name = res["reference_type"]
out = [i['money'] for i in res_data if i['reference_type'] == res["reference_type"] and i['type'] == 0]
income = [i['money'] for i in res_data if i['reference_type'] == res["reference_type"] and i['type'] == 1]
out_value = float(out[0]) if out else 0
income_value = float(income[0]) if income else 0
a = {
"name": name,
"type": res["reference_type"],
"expenditure": out_value,
"income": income_value,
"is_error": 0 if out_value == income_value else 1,
"error_money": float('%.2f' % (out_value - income_value))
}
self.structure_key.append(res["reference_type"])
self.structure_list.append(a)
# return self.data_to_table(self.structure_list) # 导出接口
return self.structure_list[(page-1)*size:page*size], len(self.structure_list)
class CalculationMonthlyDetails(object):
@staticmethod
def data_query(db, date, reference_type, is_out, page, size):
sql = f"SELECT reference_type,order_number,type,cast(amount as decimal(20,6))/1000 as money,amount_type,create_time FROM {date} where reference_type='{reference_type}' and type={is_out} LIMIT {(page-1)*size},{size}"
res_data = LinkMysql(db).query_mysql(sql)
return res_data
@staticmethod
def acquired_total(db, date, reference_type, is_out,):
sql = f"SELECT reference_type FROM {date} where reference_type='{reference_type}' and type={is_out}"
result = LinkMysql(db).query_mysql(sql)
return len(result)
def statement_income_expenditure(self, param):
database = env.MysqlDB
database["database"] = env.DB_HISTORY
with ThreadPoolExecutor(max_workers=4) as pool:
future1 = pool.submit(self.data_query, database, 'assets_log_' + param.date, param.key, param.is_income, param.page, param.size)
future2 = pool.submit(self.acquired_total, database, 'assets_log_' + param.date, param.key, param.is_income)
data = future1.result()
num = future2.result()
return data, num
from typing import Optional
from pydantic import BaseModel
from pydantic import BaseModel, validator
from pydantic import ValidationError
class ExportList(BaseModel):
......@@ -13,3 +14,20 @@ class ExportList(BaseModel):
class ExportUpdateData(BaseModel):
id: int
remark: str = ""
class MonthStatistics(BaseModel):
date: str = ""
page: int
size: int
class MonthDetails(MonthStatistics):
key: str
is_income: int
# @validator('key')
# def key_must_contain_space(cls, v):
# if ' ' not in v:
# raise ValidationError('缺少必传参数key')
# return v.title()
from datetime import datetime
from dateutil.relativedelta import relativedelta
from fastapi import Depends, APIRouter
from sqlalchemy.orm import Session
from app import get_db
......@@ -37,3 +39,22 @@ def export_source_query(db: Session = Depends(get_db)):
"""导出来源查询"""
result = crud.get_source_data(db)
return HttpResultResponse(data=result)
@router.post("/month/total")
def month_query_total_export(param: schemas.MonthStatistics):
"""月度表计算"""
if not param.date:
month_date = datetime.now().date() - relativedelta(months=1)
param.date = month_date.strftime("%Y%m")
result, num = crud.CalculationMonthlyBill().month_statistics_task('assets_log_' + param.date, param.page, param.size)
return HttpResultResponse(total=num, data=result)
@router.post("/month/details")
def month_query_total_export(param: schemas.MonthDetails):
"""月度计算,详情"""
if not param.date:
return HttpResultResponse(msg='查询月份不能为空')
result, num = crud.CalculationMonthlyDetails().statement_income_expenditure(param)
return HttpResultResponse(total=num, data=result)
......@@ -30,6 +30,7 @@ client = CosS3Client(config)
COS_PATH ='https://fj-dc-test-1256890024.cos.ap-guangzhou.myqcloud.com' #测试
COS_RERURN_PATH='/images/'
class Env(BaseSettings):
DEBUG: bool = True
TESTING: bool = False
......@@ -46,7 +47,7 @@ class Env(BaseSettings):
SECRET_KEY: str = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM: str = "HS256"
PASSWORD: str = "fj123456"
DB_HISTORY = "3y_history"
class TestingEnv(Env):
......
TYPE_NAME = {
"updateUserNameFee": "用户昵称修改",
"updateFamilyNameFee": "粉丝群名,家族名称修改",
"userExchange": "珍珠兑换钻石(用户)",
"userRecharge": "充值",
"pay_discount": "充值-折扣",
"studioGift": "背包/直播间送礼",
"turntableIncome": "转盘",
"turntableExpend": "转盘-中奖",
"recyclingGifts": "回收礼物",
"buyIdentity": "开贵族",
"buyGuard": "开守护",
"studioBarrage": "弹幕消费",
"buyProp": "购买道具",
"bei_to_change_account": "购买bei+",
"bei_to_cancel_account": "bei+订单退款",
"signInDeductMoney": "补签",
"signInReward": "钻石奖励",
"sign_in_backpack_account": "背包礼物奖励",
"live_support": "主播扶持分配",
"room_support": "直播间扶持 - 领取钻石奖励",
"lucky_gift_jackpot": "赠送幸运礼物",
"gameReward": "暴击奖励",
"userWithdrawal": "用户提现",
"sendRedBox": "发送红包",
"userRedBox": "领红包,退还红包",
"send_diamond_red_packet": "钻石红包发送",
"get_red_packet": "钻石红包领取",
"send_diamond_red_packet_back": "钻石红包退还",
"send_gift_red_packet": "礼物红包发送",
"get_gift_red_packet": "礼物红包领取",
"send_gift_red_packet_back": "礼物红包退还",
"first_recharge_gift": "首充礼包",
"user_clean_up": "用户余额清算(线上,线下)",
"cleargiftstore": "背包礼物过期",
"daily_task": "任务奖励发放钻石",
"voiceChatFee": "语聊消费",
"helpExchange": "用户打榜兑换投票次数",
"vip_recharge": "vip购买",
"PlatformLeakRepair": "平台补漏",
"voice": "用户上麦",
"MagicHegemony": "2021.11 魔法争霸赛活动",
"Points_mall_exchange": "商城积分兑换",
"privateMessageCharge": "私信收费",
"level_gift": "升级礼包",
"zhou_xing_backpack_account": "周星奖励发放",
"zhou_xing_consumable_account": "周星奖励发放",
"NamedGift": "冠名礼物",
"whoIsUndercoverJoin": "谁是卧底游戏",
"game:NDJ": "参与游戏-扭蛋机",
"gama:KMH": "参与游戏-开盲盒",
"game_transfer": "商城礼物盲盒-许愿池,八卦象",
"gama:ZJD": "参与游戏-砸金蛋",
"guildExchange": "公会兑换-出账",
"marginRecharge": "保证金缴纳",
"pledgeDeduction": "保证金扣减",
"guildExchangeDraw": "公会钻石结算",
"fanExpansion": "公会家族扩充",
"guildTrafficPromotion": "公会流量推广",
"guildWithdrawal": "公会提现",
"guildWithdrawal_ServiceFee": "公会提现",
"free_guild_profit_Exchange": "自由公会主播收礼后产生公会管理收益",
"subordinate_guild_ti_xian": "下级公会提现",
"investmentIncome": "招商收益",
"platformRecharge": "财务后台内部转账",
"currencyUpgrade": "旧币兑换(钻石)",
"PlatformDeduction": "平台扣除",
"thrid_game_transfer_user": "游戏转用户钻石(引流转盘)",
"blind_box_mall_account_recharge": "盲盒商城账户充值(人民币)",
"pk_season": "PK赛季奖励",
"finance_admin_fix": "财务系统修复",
"pk_shout_anonymity": "pk喊话",
"pk_shout": "pk喊话",
"GameConsumption": "五子棋游戏",
"fj_shop_withdraw": "商城提现",
"fj_shop_recharge": "商城订单结算",
"physical_blind_box_recharge": "实物盲盒 - 使用抽奖券并中奖",
"blind_box_redeem_points": "实物盲盒 - 兑换积分",
"blind_box_delivery": "实物盲盒 - 提货",
"physical_blind_box_refund": "实物盲盒-回收",
"zhou_xing_consume": "周星活动购买道具(创造营)",
"zhou_xing_award": "周星活动领奖",
"talentCertification": "达人认证缴费",
"Payment": "公会解约结算平台打款",
"guild_clear": "公会结算",
"shop_complete_payment": "积分商城改版 - 支付",
"points_mall_points_return": "积分商城改版 - 退款",
"cash_payment_money_return": "积分商城改版 - 退款",
"ConsignmentPaymentConfirmation_release": "用户发布转售动态",
"ConsignmentPaymentConfirmation_callback": "用户撤销转售",
"ConsignmentPaymentConfirmation": "【礼物】购买成功",
"ConsignmentPaymentConfirmation_withdraw": "【实物】确认收货",
"ConsignmentPaymentConfirmation_dress": "【转售装扮】购买成功",
"week_star_buy_dress": "购买限定装扮装扮",
"week_star_award_diamond": "榜单奖励领取",
"game_transfer_to_platform": "游戏账户向平台账户转账",
"recharge_bag_award": "超值礼包",
"HairSpotSong": "点歌功能付费",
"RetreatSpotSong": "点歌退款(主播拒绝、用户撤销)",
"BranchSpotSong": "点歌收益分配",
"guild_transfer_to_anchor": "公会转账给用户(用户得珍珠)",
"guild_transfer_to_anchor_trans_fee": "公会转账手续费支出",
"SmashGoldenEggs": "参与游戏-钻石",
"game_backpack_account": "游戏中奖",
"turntable_game_balance_add": "用户中奖",
"collection": "天外物舱-购买礼物使用权",
"fairy_star_consume": "①、3月仙女活动②、2022【贝洛的愿望】-道具购买",
"relic_buy_prop": "2022-11_遗迹修复活动-购买道具",
"relic_recharge": "2022-11_遗迹修复活动-活动充值",
"seven_country_award": "2022_七国游记活动-榜单奖励领取",
"time_detective_award": "时空侦探活动-榜单领奖",
"translate": "翻译付费",
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment