From 9bf97624b45f3e1e53a87acd08c7261a21abe63a Mon Sep 17 00:00:00 2001 From: P3ngSaM <61768364+P3ngSaM@users.noreply.github.com> Date: Fri, 24 Feb 2023 15:27:19 +0800 Subject: [PATCH] =?UTF-8?q?changes=20=E9=A9=BE=E9=A9=B6=E8=88=B1=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Crud/DailyCrud.py | 33 ++++++++++ Crud/InfoCrud.py | 36 +++++++++++ Crud/ProjectCrud.py | 124 ++++++++++++++++++++++++++++++++++++++ Model/ItemCrudModel.py | 63 ++++++++----------- Router/DaliyRouter.py | 51 ++++++++++++++++ Router/InfoRouter.py | 49 ++++++++++++++- Router/ProjectRouter.py | 105 +++++++++++++++++++++++++++++++- Router/ReportRouter.py | 6 -- Schemas/DailySchemas.py | 7 +++ Schemas/InfoSchemas.py | 7 +++ Schemas/ProjectSchemas.py | 29 +++++++++ Utils/SqlAlchemyUtils.py | 6 +- main.py | 10 +-- requirements.txt | 4 +- 14 files changed, 474 insertions(+), 56 deletions(-) create mode 100644 Crud/DailyCrud.py create mode 100644 Crud/InfoCrud.py create mode 100644 Crud/ProjectCrud.py create mode 100644 Router/DaliyRouter.py delete mode 100644 Router/ReportRouter.py create mode 100644 Schemas/DailySchemas.py create mode 100644 Schemas/InfoSchemas.py diff --git a/Crud/DailyCrud.py b/Crud/DailyCrud.py new file mode 100644 index 0000000..1e147a3 --- /dev/null +++ b/Crud/DailyCrud.py @@ -0,0 +1,33 @@ +from sqlalchemy import func +from sqlalchemy.orm import Session +from Model.ItemCrudModel import DepartmentalDailyReports +from Schemas import DailySchemas +import datetime + + +def insert_data(db: Session, schemas: dict): + # 新建填报数据,并将财报开始日期和财报结束日期存入mongodb,返回obj_id进行保存 + item = DepartmentalDailyReports(**schemas) + + db.add(item) + db.commit() + db.refresh(item) + return item + + +def query_daily(db: Session, schema: DailySchemas.QueryDaily): + department = schema.department + year = schema.year + week = schema.week + # 默认传部门自动获取该年度该周的数据 + if not week: + # 计算第几周 + today = datetime.date.today() + year_start = datetime.date(today.year, 1, 1) + week = (today - year_start).days // 7 + 1 + + result = db.query(DepartmentalDailyReports).filter(DepartmentalDailyReports.department == department, + func.year(DepartmentalDailyReports.work_date) == year, + func.week(DepartmentalDailyReports.work_date) == week).all() + + return result diff --git a/Crud/InfoCrud.py b/Crud/InfoCrud.py new file mode 100644 index 0000000..5408d60 --- /dev/null +++ b/Crud/InfoCrud.py @@ -0,0 +1,36 @@ +from sqlalchemy.orm import Session + +from Model.ItemCrudModel import InformationDataSheet +from Schemas import InfoSchemas + + +def insert_data(db: Session, schemas: dict): + # 新建填报数据,并将财报开始日期和财报结束日期存入mongodb,返回obj_id进行保存 + item = InformationDataSheet(**schemas) + + db.add(item) + db.commit() + db.refresh(item) + return item + + +def query_data_by_type(db: Session, schema: InfoSchemas.QueryInfoByType): + info_type = schema.type + page = schema.page + pagesize = schema.pagesize + + item = db.query(InformationDataSheet).filter_by(type=info_type).first() + if not item: + return False + + page = 1 if page < 1 else (100 if page > 100 else page) + pagesize = 5 if pagesize < 5 else (10 if pagesize > 10 else pagesize) + + items = db.query(InformationDataSheet).filter_by(type=info_type).offset( + (page - 1) * pagesize).limit(pagesize).all() + count = db.query(InformationDataSheet).filter_by(type=info_type).count() + + return { + "total": count, + "items": items + } diff --git a/Crud/ProjectCrud.py b/Crud/ProjectCrud.py new file mode 100644 index 0000000..eee9ae0 --- /dev/null +++ b/Crud/ProjectCrud.py @@ -0,0 +1,124 @@ +from sqlalchemy import func +from sqlalchemy.orm import Session + +from Model.ItemCrudModel import ProjectDataSheet +from Schemas import ProjectSchemas + + +def insert_data(db: Session, schemas: dict): + # 新建填报数据,并将财报开始日期和财报结束日期存入mongodb,返回obj_id进行保存 + item = ProjectDataSheet(**schemas) + + db.add(item) + db.commit() + db.refresh(item) + return item + + +def edit_data(db: Session, project_id: int, project_info: ProjectSchemas.EditProjectInfo): + item = db.query(ProjectDataSheet).filter_by(id=project_id).first() + if not item: + return False + project_info = project_info.dict() + db.query(ProjectDataSheet).filter_by(id=project_id).update(project_info) + db.commit() + return db.query(ProjectDataSheet).filter_by(id=project_id).first() + + +def query_data_by_department(db: Session, schema: ProjectSchemas.QueryProjectByDepartment): + department = schema.department + page = schema.page + pagesize = schema.pagesize + + item = db.query(ProjectDataSheet).filter_by(departments=department).first() + if not item: + return False + + page = 1 if page < 1 else (100 if page > 100 else page) + pagesize = 5 if pagesize < 5 else (10 if pagesize > 10 else pagesize) + + items = db.query(ProjectDataSheet).filter_by(departments=department).offset( + (page - 1) * pagesize).limit(pagesize).all() + count = db.query(ProjectDataSheet).filter_by(departments=department).count() + + return { + "total": count, + "items": items + } + + +def query_data_by_id(db: Session, project_id: int): + item = db.query(ProjectDataSheet).filter_by(id=project_id).first() + if not item: + return False + return item + + +def query_data_for_pie(db: Session, schema: ProjectSchemas.QueryProjectByType): + search_type = schema.type + year = schema.year + search_type_list = ["主体评级", "债项评级", "贷后监管", "绿色业务", "其他"] + if search_type == '累计收入': + result = list() + for type_item in search_type_list: + item = dict() + item['name'] = type_item + value = db.query(func.sum(ProjectDataSheet.amount)).filter( + ProjectDataSheet.project_type.in_([type_item]), + func.year(ProjectDataSheet.start_date) == year, + ).scalar() + item['value'] = round(value, 2) + result.append(item) + elif search_type == '业务数量': + result = list() + for type_item in search_type_list: + item = dict() + item['name'] = type_item + item['value'] = db.query(ProjectDataSheet).filter( + ProjectDataSheet.project_type.in_([type_item]), + func.year(ProjectDataSheet.start_date) == year, + ).count() + result.append(item) + else: + result = False + + return result + + +def query_data_for_bar(db: Session, schema: ProjectSchemas.QueryProjectByType): + search_type = schema.type + year = schema.year + year_list = [year, int(year) - 1] + search_type_list = ["主体评级", "债项评级", "贷后监管", "绿色业务", "其他"] + if search_type == '收入同比': + result = list() + for month in range(1, 13): + for y in year_list: + item = dict() + item['year'] = str(y) + '年' + item['month'] = str(month) + '月' + value = db.query(func.sum(ProjectDataSheet.amount)).filter( + func.year(ProjectDataSheet.start_date) == y, + func.month(ProjectDataSheet.start_date) == month + ).scalar() + item['value'] = 0 if value is None else value + result.append(item) + elif search_type == '业务分类': + result = list() + for type_item in search_type_list: + item = dict() + item['name'] = type_item + value = list() + for month in range(1, 13): + data = db.query(ProjectDataSheet).filter( + ProjectDataSheet.project_type.in_([type_item]), + func.year(ProjectDataSheet.start_date) == year, + func.month(ProjectDataSheet.start_date) == month + ).count() + value.append(data) + item['value'] = value + result.append(item) + else: + result = False + + return result diff --git a/Model/ItemCrudModel.py b/Model/ItemCrudModel.py index 3d81b84..540cf1b 100644 --- a/Model/ItemCrudModel.py +++ b/Model/ItemCrudModel.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, String, Float, Integer, DateTime, func, Date, Enum +from sqlalchemy import Column, String, Float, Integer, DateTime, Date, Enum from sqlalchemy.dialects.mysql import LONGTEXT from Schemas.ProjectSchemas import WorkStatusEnum, ProjectStatusEnum @@ -6,30 +6,14 @@ from Utils.CrudUtils import auto_create_crud from Utils.SqlAlchemyUtils import Base -class ItemModel(Base): - __tablename__ = 'items' - id = Column(Integer, primary_key=True, index=True) - thickness = Column(Float) - mass = Column(Float) - color = Column(String(32)) - type = Column(String(32)) - create_time = Column(DateTime, server_default=func.now(), comment='创建时间') - update_time = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment='修改时间') - - def to_dict(self): - return {c.name: getattr(self, c.name) for c in self.__table__.columns} - - -item_crud = auto_create_crud(ItemModel, 'item', '条目') - - class DepartmentalDailyReports(Base): __tablename__ = 'departmental_daily_reports' id = Column(Integer, primary_key=True, index=True) - department = Column(String(32)) - staff_name = Column(String(32)) - work_date = Column(Date) - work_status = Column(Enum(WorkStatusEnum, values_callable=lambda x: [e.value for e in x])) + department = Column(String(32), default=None) + staff_name = Column(String(32), default=None) + work_date = Column(Date, default=None) + work_content = Column(LONGTEXT, default=None) + work_status = Column(Enum(WorkStatusEnum, values_callable=lambda x: [e.value for e in x]), default=None) def to_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} @@ -41,19 +25,19 @@ reports_model = auto_create_crud(DepartmentalDailyReports, 'departmental_daily_r class ProjectDataSheet(Base): __tablename__ = 'project_data_sheet' id = Column(Integer, primary_key=True, index=True) - project = Column(String(32)) - client = Column(String(32)) - client_labels = Column(String(128)) - master = Column(String(32)) - participants = Column(String(128)) - departments = Column(String(128)) - project_type = Column(String(128)) - project_labels = Column(String(128)) - project_status = Column(Enum(ProjectStatusEnum, values_callable=lambda x: [e.value for e in x])) - start_date = Column(Date) - finish_date = Column(Date) - amount = Column(Float) - remarks = Column(LONGTEXT) + project = Column(String(128), default=None) + client = Column(String(32), default=None) + client_labels = Column(String(128), default=None) + master = Column(String(32), default=None) + participants = Column(String(128), default=None) + departments = Column(String(128), default=None) + project_type = Column(String(128), default=None) + project_labels = Column(String(128), default=None) + project_status = Column(Enum(ProjectStatusEnum, values_callable=lambda x: [e.value for e in x]), default=None) + start_date = Column(Date, default=None) + finish_date = Column(Date, default=None) + amount = Column(Float, default=None) + remarks = Column(LONGTEXT, default=None) def to_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} @@ -65,10 +49,11 @@ projects_model = auto_create_crud(ProjectDataSheet, 'project_data_sheet', '项 class InformationDataSheet(Base): __tablename__ = 'information_data_sheet' id = Column(Integer, primary_key=True, index=True) - title = Column(String(128)) - post_time = Column(DateTime) - source = Column(String(128)) - link = Column(String(128)) + title = Column(String(128), default=None) + post_time = Column(DateTime, default=None) + source = Column(String(128), default=None) + link = Column(String(128), default=None) + type = Column(String(128), default=None) def to_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} diff --git a/Router/DaliyRouter.py b/Router/DaliyRouter.py new file mode 100644 index 0000000..8b8d6a0 --- /dev/null +++ b/Router/DaliyRouter.py @@ -0,0 +1,51 @@ +import math + +from fastapi import APIRouter, UploadFile, File, Depends, HTTPException +import pandas as pd +from sqlalchemy.orm import Session + +from Crud import DailyCrud +from Schemas import DailySchemas +from Utils.SqlAlchemyUtils import get_db + +router = APIRouter( + tags=["部门日报"], + prefix="/api/daily", +) + + +@router.post("/upload", summary='日报录入', description='录入部门日报') +async def create_upload_file(file: UploadFile = File(...), db: Session = Depends(get_db)): + # 使用 Pandas 读取 Excel 文件 + df = pd.read_csv(file.file) + for index, row in df.iterrows(): + insert = { + "department": row[0], + "staff_name": row[1], + "work_date": row[2], + "work_content": row[3], + "work_status": row[4], + } + for key, val in insert.items(): + if isinstance(insert.get(key), str): + continue + elif insert.get(key) is None: + continue + elif math.isnan(insert.get(key)): + insert[key] = None + DailyCrud.insert_data(db, insert) + return { + "code": 200, + "message": "录入成功", + "content": {} + } + + +@router.post("/query", summary='日报查询', description='查询部门日报') +def func(schema: DailySchemas.QueryDaily, db: Session = Depends(get_db)): + result = DailyCrud.query_daily(db, schema) + return { + "code": 200, + "message": "查询成功", + "content": result + } \ No newline at end of file diff --git a/Router/InfoRouter.py b/Router/InfoRouter.py index 701fc88..ca41cb4 100644 --- a/Router/InfoRouter.py +++ b/Router/InfoRouter.py @@ -1,6 +1,53 @@ -from fastapi import APIRouter +import math + +import pandas as pd +from fastapi import APIRouter, UploadFile, File, Depends, HTTPException +from sqlalchemy.orm import Session + +from Crud import InfoCrud +from Schemas import InfoSchemas +from Utils.SqlAlchemyUtils import get_db router = APIRouter( tags=["资讯数据"], prefix="/api/info", ) + + +@router.post("/information_data_sheet/upload", summary='资讯录入', description='录入资讯数据') +async def func(file: UploadFile = File(...), db: Session = Depends(get_db)): + # 使用 Pandas 读取 Excel 文件 + df = pd.read_csv(file.file) + for index, row in df.iterrows(): + insert = { + "title": row[0], + "link": row[1], + "post_time": row[2], + "source": row[3], + "type": row[4] + } + for key, val in insert.items(): + if isinstance(insert.get(key), str): + continue + elif insert.get(key) is None: + continue + elif math.isnan(insert.get(key)): + insert[key] = None + InfoCrud.insert_data(db, insert) + return { + "code": 200, + "message": "录入成功", + "content": {} + } + + +@router.post("/query_by_type", summary='资讯查询', description='查询资讯数据') +def func(schema: InfoSchemas.QueryInfoByType, db: Session = Depends(get_db)): + result = InfoCrud.query_data_by_type(db, schema) + if not result: + raise HTTPException(status_code=404, detail="部门不存在") + return { + "code": 200, + "message": "查询成功", + "content": result + } \ No newline at end of file diff --git a/Router/ProjectRouter.py b/Router/ProjectRouter.py index b395fa1..e8e2cfc 100644 --- a/Router/ProjectRouter.py +++ b/Router/ProjectRouter.py @@ -1,6 +1,109 @@ -from fastapi import APIRouter +import math + +from fastapi import APIRouter, UploadFile, File, Depends, HTTPException +import pandas as pd +from sqlalchemy.orm import Session + +from Crud import ProjectCrud +from Schemas import ProjectSchemas +from Utils.SqlAlchemyUtils import get_db router = APIRouter( tags=["项目数据"], prefix="/api/project", ) + + +@router.post("/upload", summary='项目录入', description='录入项目数据') +async def func(file: UploadFile = File(...), db: Session = Depends(get_db)): + # 使用 Pandas 读取 Excel 文件 + df = pd.read_csv(file.file) + for index, row in df.iterrows(): + insert = { + "project": row[0], + "client": row[1], + "client_labels": row[2].strip("[]").replace("'", ""), + "project_type": row[3].strip("[]").replace("'", ""), + "project_labels": row[4].strip("[]").replace("'", ""), + "project_status": row[5], + "start_date": row[6], + "finish_date": row[7], + "amount": row[8], + "master": row[9], + "participants": row[10].strip("[]").replace("'", ""), + "departments": row[11].strip("[]").replace("'", ""), + "remarks": None + } + for key, val in insert.items(): + if isinstance(insert.get(key), str): + continue + elif insert.get(key) is None: + continue + elif math.isnan(insert.get(key)): + insert[key] = None + ProjectCrud.insert_data(db, insert) + return { + "code": 200, + "message": "录入成功", + "content": {} + } + + +@router.put("/edit", summary='项目编辑', description='编辑项目数据') +def func(project_id: int, project_info: ProjectSchemas.EditProjectInfo, db: Session = Depends(get_db)): + result = ProjectCrud.edit_data(db, project_id, project_info) + if not result: + raise HTTPException(status_code=404, detail="id不存在") + return { + "code": 200, + "message": "编辑成功", + "content": result + } + + +@router.post("/query_by_department", summary='部门项目查询', description='查询项目数据') +def func(schema: ProjectSchemas.QueryProjectByDepartment, db: Session = Depends(get_db)): + result = ProjectCrud.query_data_by_department(db, schema) + if not result: + raise HTTPException(status_code=404, detail="部门不存在") + return { + "code": 200, + "message": "查询成功", + "content": result + } + + +@router.post("/query_by_id", summary='id查询项目', description='查询项目数据') +def func(project_id: int, db: Session = Depends(get_db)): + result = ProjectCrud.query_data_by_id(db, project_id) + if not result: + raise HTTPException(status_code=404, detail="id不存在") + return { + "code": 200, + "message": "查询成功", + "content": result + } + + +@router.post("/query_by_pie", summary='累计收入业务数量查询', description='查询项目数据') +def func(schema: ProjectSchemas.QueryProjectByType, db: Session = Depends(get_db)): + result = ProjectCrud.query_data_for_pie(db, schema) + if not result: + raise HTTPException(status_code=404, detail="类别不存在") + return { + "code": 200, + "message": "查询成功", + "content": result + } + + +@router.post("/query_by_bar", summary='收入同比业务分类查询', description='查询项目数据') +def func(schema: ProjectSchemas.QueryProjectByType, db: Session = Depends(get_db)): + result = ProjectCrud.query_data_for_bar(db, schema) + if not result: + raise HTTPException(status_code=404, detail="类别不存在") + return { + "code": 200, + "message": "查询成功", + "content": result + } \ No newline at end of file diff --git a/Router/ReportRouter.py b/Router/ReportRouter.py deleted file mode 100644 index 706edc0..0000000 --- a/Router/ReportRouter.py +++ /dev/null @@ -1,6 +0,0 @@ -from fastapi import APIRouter - -router = APIRouter( - tags=["部门日报"], - prefix="/api/daily", -) diff --git a/Schemas/DailySchemas.py b/Schemas/DailySchemas.py new file mode 100644 index 0000000..a39f48a --- /dev/null +++ b/Schemas/DailySchemas.py @@ -0,0 +1,7 @@ +from pydantic import BaseModel + + +class QueryDaily(BaseModel): + department: str + year: str + week: int diff --git a/Schemas/InfoSchemas.py b/Schemas/InfoSchemas.py new file mode 100644 index 0000000..b3e28c7 --- /dev/null +++ b/Schemas/InfoSchemas.py @@ -0,0 +1,7 @@ +from pydantic import BaseModel + + +class QueryInfoByType(BaseModel): + type: str + page: int = 1 + pagesize: int = 10 diff --git a/Schemas/ProjectSchemas.py b/Schemas/ProjectSchemas.py index 634f25c..94d44ee 100644 --- a/Schemas/ProjectSchemas.py +++ b/Schemas/ProjectSchemas.py @@ -1,5 +1,7 @@ from enum import Enum, unique +from pydantic import BaseModel + @unique class WorkStatusEnum(Enum): @@ -13,3 +15,30 @@ class ProjectStatusEnum(Enum): enum01 = "进行" enum02 = "完成" enum03 = "终止" + + +class EditProjectInfo(BaseModel): + project: str + client: str + client_labels: str + master: str + participants: str + departments: str + project_type: str + project_labels: str + project_status: str + start_date: str + finish_date: str + amount: str + remarks: str + + +class QueryProjectByDepartment(BaseModel): + department: str + page: int = 1 + pagesize: int = 10 + + +class QueryProjectByType(BaseModel): + type: str + year: str diff --git a/Utils/SqlAlchemyUtils.py b/Utils/SqlAlchemyUtils.py index f9c12be..5d42674 100644 --- a/Utils/SqlAlchemyUtils.py +++ b/Utils/SqlAlchemyUtils.py @@ -5,9 +5,9 @@ from sqlalchemy.orm import sessionmaker Base = declarative_base() USER = "root" -PASSWORD = "12345" -HOST = "127.0.0.1" -DB = "user" +PASSWORD = "123456" +HOST = "localhost:3306" +DB = "wr_cockpit" def get_engine(): diff --git a/main.py b/main.py index 5c73f75..d6018a0 100644 --- a/main.py +++ b/main.py @@ -1,15 +1,15 @@ import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from Router import InfoRouter, ProjectRouter, ReportRouter +from Router import InfoRouter, ProjectRouter, DaliyRouter from Model.ItemCrudModel import reports_model, projects_model, information_model from Utils.SqlAlchemyUtils import init_database init_database() -reports_model.mount(ReportRouter.router) -projects_model.mount(ProjectRouter.router) -information_model.mount(InfoRouter.router) +# reports_model.mount(DaliyRouter.router) +# projects_model.mount(ProjectRouter.router) +# information_model.mount(InfoRouter.router) app = FastAPI( @@ -25,7 +25,7 @@ app.add_middleware( allow_headers=["*"], ) -app.include_router(ReportRouter.router) +app.include_router(DaliyRouter.router) app.include_router(ProjectRouter.router) app.include_router(InfoRouter.router) diff --git a/requirements.txt b/requirements.txt index a66c6f3..ea5e32d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,6 @@ requests==2.28.2 captcha==0.4 pymysql==1.0.2 fastapi-crudrouter==0.8.6 -redis==4.5.1 \ No newline at end of file +redis==4.5.1 +pandas==1.5.3 +python-multipart==0.0.5 \ No newline at end of file