From f5998c14a5460e82c765bc2a524495f2da597cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=80=C3=AE=C3=97=C3=9A=C3=95=C3=B1?= Date: Wed, 20 Jul 2022 15:52:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=80=99=E9=80=89=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api_v1/api.py | 2 + api/api_v1/endpoints/forms.py | 38 +++++++++ models/interview_zsgc.py | 154 ++++++++++++++++++++++++++++++---- utils/func.py | 50 +++++++++++ 4 files changed, 227 insertions(+), 17 deletions(-) create mode 100644 api/api_v1/endpoints/forms.py diff --git a/api/api_v1/api.py b/api/api_v1/api.py index 65680ed..862e772 100644 --- a/api/api_v1/api.py +++ b/api/api_v1/api.py @@ -10,6 +10,7 @@ from .endpoints import data_mana from .endpoints import query from .endpoints import xquery from .endpoints import interview +from .endpoints import forms from .endpoints import data_auth from .endpoints import event_mana from .endpoints import test @@ -41,4 +42,5 @@ api_router.include_router(check_data.router, tags=["打点验证"], prefix='/che api_router.include_router(user_label.router, tags=["用户标签"], prefix='/user_label') api_router.include_router(interview.router, tags=["面试数据管理"], prefix='/itr') +api_router.include_router(forms.router, tags=["hr报表模板管理"], prefix='/forms') diff --git a/api/api_v1/endpoints/forms.py b/api/api_v1/endpoints/forms.py new file mode 100644 index 0000000..cf0a20f --- /dev/null +++ b/api/api_v1/endpoints/forms.py @@ -0,0 +1,38 @@ +import operator +import os +import re +import pandas as pd +from fastapi import APIRouter, Depends, Request, File, UploadFile +from motor.motor_asyncio import AsyncIOMotorDatabase + +from utils.dingding import get_redis_alluid, send_dates +from utils.jianli import get_resume +import crud, schemas +from datetime import datetime +from core.configuration import * +from db import get_database +from db.ckdb import get_ck_db, CKDrive + +from models.interview_zsgc import InterviewDo +from utils import get_time, qujian_time, Download_xlsx, send_str_mail + +router = APIRouter() + + +# 候选人质量报表 +@router.post("/man_mass_form") +async def interview_find( + request: Request, + interview: InterviewDo = Depends(InterviewDo), + db: CKDrive = Depends(get_ck_db), +) -> schemas.Msg: + """ interview面试数据查询 """ + await interview.init() + res = interview.get_man_mass_form_sql() + sql = res['sql'] + # data = await db.execute(sql) + df = await db.query_dataframe(sql) + if df.empty: + return schemas.Msg(code=-9, msg='无数据', data=None) + + # return schemas.Msg(code=200, msg='ok', data=data) diff --git a/models/interview_zsgc.py b/models/interview_zsgc.py index 0a9b2d8..384a0f7 100644 --- a/models/interview_zsgc.py +++ b/models/interview_zsgc.py @@ -20,6 +20,7 @@ from db import get_database from db.redisdb import get_redis_pool, RedisDrive from models.user_label import UserClusterDef +from utils import get_week, strptime, start_end_month, strptime1 # 面试数据ck增删改查 @@ -35,6 +36,77 @@ class InterviewDo: self.data_in = self.query_in.data_in self.where = self.query_in.interview_query + def handler_filts(self, where): + """ + + :param filters: (filts:list,relation:str) + :param g_f: + :param relation: + :return: + """ + + filters = [] + for col, value in where.items(): + filters.append(col == value) + return filters + + async def scatter_model_sql(self): + time = self.where.get('time', '') + start_time0 = self.where.get('start_time', '') + end_time0 = self.where.get('end_time', '') + global where + # 判断是分布分析里面的分组详情,改时间范围,其他情况都走else + if time != '': + timeParticleSize = self.where.get('timeParticleSize', 'P1M') # 筛选是按周,按月,合计等情况,用不同的时间 + if timeParticleSize == 'P1W': # 按周 + start_date, end_date = get_week(time) + if start_date < strptime(start_time0): # 开头的时间 + where = [ + func.addHours("event_time") >= start_time0, + func.addHours("event_time") <= end_date, + ] + elif end_date < strptime(end_time0): # 中间的时间 + where = [ + func.addHours("event_time") >= start_date, + func.addHours("event_time") <= end_date, ] + else: # 结尾的时间 + where = [ + func.addHours("event_time") >= start_date, + func.addHours("event_time") <= end_time0, ] + elif timeParticleSize == 'P1M': # 按月 + start_date, end_date = start_end_month(time) + if strptime(start_time0) > strptime1(time): + where = [ + func.addHours("event_time") >= start_time0, + func.addHours("event_time") <= end_date, + ] + else: + where = [ + func.addHours("event_time") >= start_date, + func.addHours("event_time") <= end_time0, + ] + else: + where = [ + func.addHours("event_time") >= start_time0, + func.addHours("event_time") <= end_time0, ] + else: + where = [ + func.addHours("event_time") >= start_time0, + func.addHours("event_time") <= end_time0, + ] + + filter = self.handler_filts(self.where) + where.extend(filter) + + qry = sa.select(*self.find_column).where(and_(*where)) + + sql = str(qry.compile(compile_kwargs={"literal_binds": True})) + print(sql) + return { + 'sql': sql + } + + # 插入面试数据 def insert_interview_sql(self): # 简历初始文档 data_mode = { @@ -145,10 +217,12 @@ class InterviewDo: append_data.update(data_true) res_data.append(append_data) print(sql) - return {'sql': sql, - 'insert_data': res_data - } + return { + 'sql': sql, + 'insert_data': res_data + } + # 更新面试数据sql def update_interview_sql(self): updateStr = '' whereStr = '' @@ -167,8 +241,9 @@ class InterviewDo: sql = f"alter table HR.resumes update {updateStr} where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } def find_interview_sql(self): whereStr = '' @@ -185,8 +260,9 @@ class InterviewDo: sql = f"select {findStr} from HR.resumes where {whereStr}" # sql = f"select * from HR.resumes where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } # 主页初筛查询 def find_interview_home_sql(self): @@ -208,8 +284,9 @@ class InterviewDo: findStr = findStr.strip().strip(',') sql = f"select {findStr} from HR.resumes where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } # 复筛查询 def find_interview_screen_sql(self): @@ -231,8 +308,9 @@ class InterviewDo: findStr = findStr.strip().strip(',') sql = f"select {findStr} from HR.resumes where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } # 面试阶段查询 def find_interview_exam_sql(self): @@ -254,8 +332,9 @@ class InterviewDo: findStr = findStr.strip().strip(',') sql = f"select {findStr} from HR.resumes where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } # offer阶段查询 def find_interview_offer_sql(self): @@ -277,8 +356,9 @@ class InterviewDo: findStr = findStr.strip().strip(',') sql = f"select {findStr} from HR.resumes where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } # 待入职阶段查询 def find_interview_waite_in_sql(self): @@ -301,8 +381,48 @@ class InterviewDo: findStr = findStr.strip().strip(',') sql = f"select {findStr} from HR.resumes where {whereStr}" print(sql) - return {'sql': sql, - } + return { + 'sql': sql, + } + + # 分组报表候选人质量查询 + def get_man_mass_form_sql(self): + whereStr = '' + findStr = '' + # 查询字段 + self.find_column = ["uid", "age", "gender", "name", "education", "owner_name", "school", "specialty", + "work_exp", "job_name", "account"] + for fstr in self.find_column: + findStr += fstr + ', ' + is_date = 0 + for key, value in self.where.items(): + if key in ['start_time', 'end_time']: + is_date = 1 + continue + if isinstance(value, str): + whereStr += str(key) + ' = ' + "'" + value + "'" + ' ' + continue + whereStr += str(key) + ' = ' + str(value) + ' ' + whereStr = whereStr.strip() + findStr = findStr.strip().strip(',') + + # 有日期条件 + if is_date: + start_time = self.where.get('start_time', '') + end_time = self.where.get('end_time', '') + sql = f"select {findStr} from HR.resumes where {whereStr}" + if start_time: + sql += f" and toDate(event_time) >= `{start_time}`" + if end_time: + sql += f" and toDate(event_time) <= `{end_time}`" + # 没有日期条件 + else: + sql = f"select {findStr} from HR.resumes where {whereStr}" + + print(sql) + return { + 'sql': sql + } if __name__ == '__main__': diff --git a/utils/func.py b/utils/func.py index 0f421cb..e17ddc2 100644 --- a/utils/func.py +++ b/utils/func.py @@ -6,6 +6,10 @@ import smtplib from email.mime.text import MIMEText from email.utils import formataddr +from datetime import timedelta +from datetime import datetime as p1 +import calendar + from core.config import Email @@ -230,3 +234,49 @@ def send_str_mail(str_msg, my_user): # server.sendmail(my_sender, [my_user, ], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件 server.sendmail(Email.my_sender, [my_user, ], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件 server.quit() # 关闭连接 + + +def get_week(date_str=None): + if date_str and isinstance(date_str, str): + now_time = (p1.strptime(date_str + " 00:00:00", "%Y-%m-%d %H:%M:%S") + datetime.timedelta(days=1)).strftime( + "%Y-%m-%d %H:%M:%S") + else: + now_time = p1.now().replace(hour=0, minute=0, second=0, microsecond=0) + now_time = strptime(now_time) + # 当前日期所在周的周一 + week_start_time = now_time - timedelta(days=now_time.weekday() + 1, hours=now_time.hour, minutes=now_time.minute, + seconds=now_time.second) + # 当前日期所在周的周日 + week_end_time = week_start_time + timedelta(days=6, hours=23, minutes=59, seconds=59) + return week_start_time, week_end_time + + +def strptime(date_string): + """ + 将字符串转换成datetime.datetime类型 + :param date_string: '2022-05-29 23:59:59' + :return: 2022-05-29 23:59:59 + """ + return p1.strptime(date_string, '%Y-%m-%d %H:%M:%S') + + +def strptime1(date_str): + """ + 将字符串转换成datetime.datetime类型 + :param date_string: '2022-05-29' + :return: 2022-05-29 00:00:00 + """ + return p1.strptime(date_str + " 00:00:00", "%Y-%m-%d %H:%M:%S") + + +def start_end_month(time): + """ + 获取某个月的起始时间和结束时间 + :param time: '2022-05-29' + :return: + """ + now = p1.strptime(time + " 00:00:00", "%Y-%m-%d %H:%M:%S") + this_month_start = datetime.datetime(now.year, now.month, 1) + this_month_end = datetime.datetime(now.year, now.month, calendar.monthrange(now.year, now.month)[1]) + this_month_end1 = this_month_end + timedelta(hours=23, minutes=59, seconds=59) + return this_month_start, this_month_end1 \ No newline at end of file