From b56e61a7bdb2f2db5dc59e55c64ba7788f72d7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BC=9F?= <250213850@qq.com> Date: Wed, 2 Nov 2022 17:50:07 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BC=98=E5=8C=96=E4=BA=BA=E6=89=8D=E5=BA=93?= =?UTF-8?q?=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api_v1/endpoints/interview.py | 249 ++++++++++++++++++++++++++---- crud/crud_feedback.py | 2 +- models/interview_zsgc.py | 2 +- schemas/feedback.py | 1 + schemas/talentpool_filtrate.py | 4 +- schemas/user.py | 2 +- utils/dingding.py | 5 +- utils/func.py | 2 +- 8 files changed, 228 insertions(+), 39 deletions(-) diff --git a/api/api_v1/endpoints/interview.py b/api/api_v1/endpoints/interview.py index 6d3b17e..3bdd38f 100644 --- a/api/api_v1/endpoints/interview.py +++ b/api/api_v1/endpoints/interview.py @@ -22,7 +22,7 @@ from schemas import ExtendendOAuth from utils.dingding import * from utils.jianli import get_resume from utils.re_to_jianli import fmt_txt, getText_pdf -from utils.func import get_uid, send_affix_mail +from utils.func import get_uid, send_affix_mail, judge, hours import crud, schemas from datetime import datetime from core.configuration import * @@ -377,6 +377,7 @@ async def interview_update( await interview.init() res = interview.update_interview_sql() sql = res['sql'] + print(sql) # try: inte_stage = interview.data_in.get('interview_stage', 0) # 修改的简历阶段 if inte_stage == 1: # 人才推荐进入初筛时分配面试官和HR @@ -405,7 +406,7 @@ async def interview_update( f"interview_stage = 1 ,hr_name = '{nicknames1}',hr_id = '{user_ids1}',", 1) interviews = int(interview.data.get('interview_stage', '0')) # 当前简历阶段 if interview.data_in.get('interview_stage', '') == 11: # 当是淘汰时则把淘汰的时间,阶段等都记录下来 - now = str(datetime.datetime.now()).split('.')[0] + now = str(datetime.now()).split('.')[0] sql = sql.replace("interview_stage = 11", f"interview_stage = 11,ago={interviews},pass_time='{now}'") data = await ckdb.execute(sql) print(sql) @@ -428,7 +429,7 @@ async def interview_update( res = await crud.user.get_users(db, userid_list) unionid_list = [i['unionid'] for i in res] Sample.create_task('淘汰通知', current_user.unionid, content, unionid_list) # 待办通知 - if interview.data_in.get('hr_manner', 10) in [0, 1]: + if interview.data_in.get('hr_manner', 10) in [0, 1]: # 1表示用人经理同意你的推荐人进入复筛阶段,0不同意 # 更新推荐记录 await crud.department.update(db, {'types': True}, interview.where.get('uid')) return schemas.Msg(code=200, msg='ok', data=data) @@ -717,7 +718,8 @@ async def file_to_hw( print('errorCode:', res.errorCode) print('errorMessage:', res.errorMessage) return schemas.Msg(code=400, msg='上传华为云失败', data=None) - except: + except Exception as e: + print(e) return schemas.Msg(code=400, msg='上传华为云失败或者解析失败', data=None) @@ -1231,6 +1233,8 @@ async def get_job( """ # 获取各个职位的候选人总数 df = await ckdb.query_dataframe(sql1) + if df.empty: + return schemas.Msg(code=-9, msg='无数据', data='') job_dict = dict(zip(df['job_id'], df['nu'])) for i in res: job_list = {} @@ -2013,11 +2017,11 @@ async def login( 'rank': user.rank, # 区分hr和面试官 'nickname': user.nickname, # 显示名 'token': security.create_access_token( - expires_delta=access_token_expires, user_id=user.user_id, email=user.email, + expires_delta=access_token_expires, user_id=user.user_id, email=user.email, nickname=user.nickname, tel=user.tel, name=user.name, rank=user.rank, unionid=user.unionid, _id=str(user.id)), "token_type": "bearer"}, 'access_token': security.create_access_token( - expires_delta=access_token_expires, user_id=user.user_id, email=user.email, + expires_delta=access_token_expires, user_id=user.user_id, email=user.email, nickname=user.nickname, tel=user.tel, name=user.name, rank=user.rank, unionid=user.unionid, _id=str(user.id) ), "token_type": "bearer", @@ -2459,6 +2463,9 @@ async def send_interviewee( 'create': str(datetime.now()).split('.')[0]} # 先查有没有推荐记录 res = await crud.department.where_dep(db, {'uid': data_in.uid}) + # 放入任务之中 + judge(**{'uid': data_in.uid, 'subject': '推荐通知', 'creator_id': current_user.unionid, + 'description': send, 'executor_ids': unionid_list, "types": False, 'times': hours()}) if res == []: # 没有则创建 await crud.department.create(db, datas) else: # 有就更新 @@ -2517,6 +2524,7 @@ async def add_interviewee( user_data = df1[0] # 存份面试数据到mongodb now_time = str(datetime.now()).split('.')[0] + relevancy_id = get_uid() await crud.interview_record.insert_record(db, {'uid': user_data['uid'], # 唯一id 'name': user_data['name'], # 求职者姓名 'interview_name': user_data['interview_name'], # 面试官姓名 @@ -2529,8 +2537,9 @@ async def add_interviewee( 'times': now_time, # 创建数据日期 'read_status': 0, # 读取状态 'back_status': 0, # 反馈状态 - 'type': 'interview' # 记录的类型 - }) + 'type': 'interview', # 记录的类型 + 'relevancy_id' : relevancy_id # 标识,关联面试反馈用 + }) # 创建空白的面试反馈到mdb数据库 survey = {} for us in [name, hr]: @@ -2543,7 +2552,7 @@ async def add_interviewee( "evaluate": "", "teacher_back": 0, 'type': False} - await crud.feedback.ins_feedback(db, schemas.Feedback(uid=data_in.uid, survey=survey)) + await crud.feedback.ins_feedback(db, schemas.Feedback(uid=data_in.uid, survey=survey,relevancy_id=relevancy_id)) return schemas.Msg(code=200, msg='ok', data='') @@ -2877,8 +2886,18 @@ async def hint( """个人面试记录""" res = [] interview = await crud.interview_record.all_fields(db, {'uid': data_in.uid}) + #面试反馈 + data = await crud.feedback.one_feedback(db, {'uid': data_in.uid}) for i in interview: i.pop('_id') + for ii in data: + if i['relevancy_id'] == ii ['relevancy_id']: + survey=[] + for k,v in ii['survey'].items(): + vlave=v + vlave['user_id']=k + survey.append(vlave) + i['survey']=survey res.append(i) data = sorted(res, key=operator.itemgetter('times')) return schemas.Msg(code=200, msg='ok', data=data) @@ -2893,8 +2912,8 @@ async def talent_pool( current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """获取人才库数据,分页查询""" - find_column = ["uid", "gender", "at_school", "name", "event_time", "education", "school", "specialty", - "work_exp", "job_id", "job_names", "ago", "pass_time""job_name", "pass_why", "pass_text"] + find_column = ["uid", "gender", "at_school", "name", "event_time", "education", "school", "specialty", "work_list", + "work_exp", "job_id", "job_names", "ago", "age", "pass_time", "job_name", "pass_why", "pass_text"] find_columns = ','.join(find_column) if data_in.date != {}: strs = [] @@ -2904,18 +2923,107 @@ async def talent_pool( strs.append(str_s) where = ' and '.join(strs) sql = f""" - select {find_columns} from HR.resumes where interview_stage = -1 and {where} ORDER BY event_time + select {find_columns} from HR.resumes where interview_stage = 11 and {where} ORDER BY event_time LIMIT 10 OFFSET {(data_in.pages - 1) * 10} """ else: sql = f""" - select {find_columns} from HR.resumes where interview_stage = -1 ORDER BY event_time + select {find_columns} from HR.resumes where interview_stage = 11 ORDER BY event_time LIMIT 10 OFFSET {(data_in.pages - 1) * 10} """ + print(sql) data = await ckdb.execute(sql) if not data: return schemas.Msg(code=-9, msg='无数据', data='') res = chkData(data) + job_id = [i['job_id'] for i in res] + # 查询对应职位数量 + sql1 = f"""select job_id,count(*) as values from HR.resumes where interview_stage = 11 and job_id in {job_id} group by job_id""" + df = await ckdb.query_dataframe(sql1) + if not df.empty: + job_dict = dict(zip(df['job_id'], df['values'])) + for i in res: + i['similarity'] = job_dict.get(i['job_id'], 0) + # res = [ + # {"uid": "3b37c7d9a4f104", "gender": "女", "at_school": "2018/09-2020/06", "name": "张双琪", + # "event_time": "2022-10-27", "education": "大专", + # "school": "湖北科技职业学院", "specialty": "移动应用开发", "work_list": [ + # { + # "company_name": "武汉筑梦科技有限公司", + # "time": "2019/07-2020/01", + # "position_name": "web前端 ", + # "duty": ": 主要从事自己负责Web前端开发。根据需求说明和设计文档,完成所分模块的开发及负责模块的单元测试工作。\n协助UI设计师完成也是设计工作,提出技术实现条件。负责前端页面的开发和前端交互的设计,以及网站前端\n性能的优化和提升\n" + # } + # ], + # "work_exp": 0, "job_id": "", "job_names": "", "ago": 1, "age": 22, "pass_time": "2022-10-28", + # "job_name": " Web开发工程师", "pass_why": "招聘需求变更", "pass_text": "dfbhg", "similarity": 11 + # }, {"uid": "3b37c7d9a4f105", "gender": "女", "at_school": "2018/09-2020/06", "name": "张双琪1", + # "event_time": "2022-10-27", "education": "大专", + # "school": "湖北科技职业学院", "specialty": "移动应用开发", "work_list": [ + # { + # "company_name": "武汉筑梦科技有限公司", + # "time": "2019/07-2020/01", + # "position_name": "web前端 ", + # "duty": ": 主要从事自己负责Web前端开发。根据需求说明和设计文档,完成所分模块的开发及负责模块的单元测试工作。\n协助UI设计师完成也是设计工作,提出技术实现条件。负责前端页面的开发和前端交互的设计,以及网站前端\n性能的优化和提升\n" + # } + # ], + # "work_exp": 0, "job_id": "", "job_names": "", "ago": 2, "age": 22, "pass_time": "2022-10-28", + # "job_name": " Web开发工程师", "pass_why": "招聘需求变更", "pass_text": "dfbhg", "similarity": 9 + # }, {"uid": "3b37c7d9a4f106", "gender": "女", "at_school": "2018/09-2020/06", "name": "张双琪2", + # "event_time": "2022-10-27", "education": "大专", + # "school": "湖北科技职业学院", "specialty": "移动应用开发", "work_list": [ + # { + # "company_name": "武汉筑梦科技有限公司", + # "time": "2019/07-2020/01", + # "position_name": "web前端 ", + # "duty": ": 主要从事自己负责Web前端开发。根据需求说明和设计文档,完成所分模块的开发及负责模块的单元测试工作。\n协助UI设计师完成也是设计工作,提出技术实现条件。负责前端页面的开发和前端交互的设计,以及网站前端\n性能的优化和提升\n" + # } + # ], + # "work_exp": 0, "job_id": "", "job_names": "", "ago": 3, "age": 28, "pass_time": "2022-10-28", + # "job_name": " Web开发工程师", "pass_why": "招聘需求变更", "pass_text": "dfbhg", "similarity": 5 + # }, {"uid": "3b37c7d9a4f107", "gender": "女", "at_school": "2018/09-2020/06", "name": "张双琪3", + # "event_time": "2022-10-27", "education": "大专", + # "school": "湖北科技职业学院", "specialty": "移动应用开发", "work_list": [ + # { + # "company_name": "武汉筑梦科技有限公司", + # "time": "2019/07-2020/01", + # "position_name": "web前端 ", + # "duty": ": 主要从事自己负责Web前端开发。根据需求说明和设计文档,完成所分模块的开发及负责模块的单元测试工作。\n协助UI设计师完成也是设计工作,提出技术实现条件。负责前端页面的开发和前端交互的设计,以及网站前端\n性能的优化和提升\n" + # } + # ], + # "work_exp": 0, "job_id": "", "job_names": "", "ago": 4, "age": 26, "pass_time": "2022-10-28", + # "job_name": " Web开发工程师", "pass_why": "招聘需求变更", "pass_text": "dfbhg", "similarity": 2 + # }, {"uid": "3b37c7d9a4f108", "gender": "女", "at_school": "2018/09-2020/06", "name": "张双琪4", + # "event_time": "2022-10-27", "education": "大专", + # "school": "湖北科技职业学院", "specialty": "移动应用开发", "work_list": [ + # { + # "company_name": "武汉筑梦科技有限公司", + # "time": "2019/07-2020/01", + # "position_name": "web前端 ", + # "duty": ": 主要从事自己负责Web前端开发。根据需求说明和设计文档,完成所分模块的开发及负责模块的单元测试工作。\n协助UI设计师完成也是设计工作,提出技术实现条件。负责前端页面的开发和前端交互的设计,以及网站前端\n性能的优化和提升\n" + # } + # ], + # "work_exp": 0, "job_id": "", "job_names": "", "ago": 5, "age": 23, "pass_time": "2022-10-28", + # "job_name": " Web开发工程师", "pass_why": "招聘需求变更", "pass_text": "dfbhg", "similarity": 0 + # }, {"uid": "3b37c7d9a4f109", "gender": "女", "at_school": "2018/09-2020/06", "name": "张双琪5", + # "event_time": "2022-10-27", "education": "大专", + # "school": "湖北科技职业学院", "specialty": "移动应用开发", "work_list": [ + # { + # "company_name": "武汉筑梦科技有限公司", + # "time": "2019/07-2020/01", + # "position_name": "web前端 ", + # "duty": ": 主要从事自己负责Web前端开发。根据需求说明和设计文档,完成所分模块的开发及负责模块的单元测试工作。\n协助UI设计师完成也是设计工作,提出技术实现条件。负责前端页面的开发和前端交互的设计,以及网站前端\n性能的优化和提升\n" + # } + # ], + # "work_exp": 0, "job_id": "", "job_names": "", "ago": 0, "age": 22, + # "pass_time": "2022-10-28", "job_name": " Web开发工程师", "pass_why": "招聘需求变更", + # "pass_text": "dfbhg", "similarity": 1 + # }, + # ] + else: + if len(res) > 0: + for i in res: + i['similarity'] = 0 return schemas.Msg(code=200, msg='ok', data=res) @@ -2932,16 +3040,20 @@ async def talent_pool_nu( strs = [] for k, v in data_in.date.items(): if v != '': - str_s = f"{k} like '%{v}%'" + if k not in ['event_time']: + str_s = f"{k} like '%{v}%'" + else: + str_s = f"{k} = '{v}'" strs.append(str_s) where = ' and '.join(strs) - sql = f"""select count(*) as nu from HR.resumes where interview_stage = -1 and {where}""" + sql = f"""select count(*) as nu from HR.resumes where interview_stage = 11 and {where}""" else: - sql = f"""select count(*) as nu from HR.resumes where interview_stage = -1""" + sql = f"""select count(*) as nu from HR.resumes where interview_stage = 11""" + print(sql) data = await ckdb.query_dataframe(sql) - if not data: + if data.empty: return schemas.Msg(code=-9, msg='无数据', data='') - res = data['nu'][0] + res = int(data['nu'][0]) return schemas.Msg(code=200, msg='ok', data=res) @@ -2974,13 +3086,26 @@ async def up_option( ) -> schemas.Msg: """修改/新增人才库筛选项""" res = await crud.talentpool_filtrate.where_filtrate(db, ['default', current_user.id]) - if len(res) > 1: # 修改自定义筛选项 + if len(res) > 1: # 修改自己的自定义筛选项 for i in res: if i['user_id'] != 'default': - await crud.talentpool_filtrate.update_filtrate(db, current_user.id, data_in.dict()) + for up_id in i['where']: + if up_id['id'] in data_in.where: + up_id['type'] = True + else: + up_id['type'] = False + i.pop('user_id') + await crud.talentpool_filtrate.update_filtrate(db, current_user.id, i) break - else: # 新增自定义筛选项 - await crud.talentpool_filtrate.ins_filtrate(db, schemas.Filtrate(**data_in.dict(), user_id=current_user.id)) + else: # 新增自己的自定义筛选项 + for i in res[0]['where']: + if i['id'] in data_in.where: + i['type'] = True + else: + i['type'] = False + res[0].pop('user_id') + await crud.talentpool_filtrate.ins_filtrate(db, + schemas.Filtrate(where=res[0]['where'], user_id=current_user.id)) return schemas.Msg(code=200, msg='ok', data='') @@ -2995,26 +3120,88 @@ async def option_data( """获取才库筛选项数据""" data = {} for i in data_in.where: - if i == 'job': # 应聘职位 + if i == 'job_id': # 应聘职位 res = await crud.jobs.where_field(db) - job = {} + job = [] for i in res: - job[i['job_id']] = i['job_name'] + job_s = {} + job_s['id'] = i['job_id'] + job_s['name'] = i['job_name'] + job.append(job_s) data['job_id'] = job elif i == 'pass_why': # 归档原因 - data['pass_why'] = pass_why_dict + pass_why = [] + for k, v in pass_why_dict.items(): + pass_w = {} + pass_w['id'] = k + pass_w['name'] = v + pass_why.append(pass_w) + data['pass_why'] = pass_why elif i == 'owner_name': # 渠道 - data['owner_name'] = owner_name_dict + owner_name = [] + for k, v in owner_name_dict.items(): + owner = {} + owner['id'] = k + owner['name'] = v + owner_name.append(owner) + data['owner_name'] = owner_name elif i == 'education': # 学历 - data['education'] = education_dict + education = [] + for k, v in education_dict.items(): + educa = {} + educa['id'] = k + educa['name'] = v + education.append(educa) + data['education'] = education elif i == 'gender': # 性别 data['gender'] = ['男', '女'] elif i == 'department': # 职位负责人 res1 = await crud.user.get_all_users(db, {'rank': 2}) - data['department'] = [{i['_id']: i['nickname']} for i in res1] + department = [] + for i in res1: + depar = {} + depar['id'] = i['_id'] + depar['name'] = i['nickname'] + department.append(depar) + data['department'] = department elif i == 'hr_name': # 候选人所有者 res2 = await crud.user.get_all_users(db, {}) - data['hr_name'] = [{i['_id']: i['nickname']} for i in res2] + hr_name = [] + for i in res2: + hr_n = {} + hr_n['id'] = i['_id'] + hr_n['name'] = i['nickname'] + hr_name.append(hr_n) + data['hr_name'] = hr_name elif i == 'ago': # 归档前的阶段 - data['ago'] = interview_stage_dict + ago = [] + for k, v in interview_stage_dict.items(): + stage = {} + stage['id'] = k + stage['name'] = v + ago.append(stage) + data['ago'] = ago + return schemas.Msg(code=200, msg='ok', data=data) + + +@router.get("/get_number") +async def option_data( + request: Request, + ckdb: CKDrive = Depends(get_ck_db), + db: AsyncIOMotorDatabase = Depends(get_database), + current_user: schemas.UserDB = Depends(deps.get_current_user) +) -> schemas.Msg: + """获取才库候选人总数和今日归档人数""" + now = datetime.now().strftime('%Y-%m-%d') + start_time = now + ' 00:00:00' + end_time = now + ' 23:59:59' + sql = f"""SELECT count(*) as values from HR.resumes where addHours(pass_time,0) >= '{start_time}' and addHours(pass_time,0) <= '{end_time}' and interview_stage = 11""" + # 今日归档人数 + print(sql) + nu = await ckdb.execute(sql) + num = nu[0]['values'] + _sql = f"""SELECT count(*) as values from HR.resumes where interview_stage <=6""" + _nu = await ckdb.execute(_sql) + _num = _nu[0]['values'] + data = {'now': num, 'candidate': _num} return schemas.Msg(code=200, msg='ok', data=data) diff --git a/crud/crud_feedback.py b/crud/crud_feedback.py index 5517001..5eca7af 100644 --- a/crud/crud_feedback.py +++ b/crud/crud_feedback.py @@ -14,7 +14,7 @@ class CRUDfeedback(CRUDBase): # 获取对应条件的数据 async def one_feedback(self, db: AsyncIOMotorDatabase,where): - return await self.find_one(db, where,{'_id':0}) + return await self.find_many(db, where,{'_id':0}) # 修改数据 async def up_feedback(self, db: AsyncIOMotorDatabase, data_in: schemas.Feedback): diff --git a/models/interview_zsgc.py b/models/interview_zsgc.py index 9aa83b5..4169172 100644 --- a/models/interview_zsgc.py +++ b/models/interview_zsgc.py @@ -605,7 +605,7 @@ class InterviewDo: "school", "specialty", "interview_name", "mmended_state", "work_list", "work_exp", "graduate_time", "job_name", "feedback", "interview_round", "interview_state", "interview_stage", "pass_why", - "pass_text"] + "pass_text","teacher_state"] for fstr in self.find_column: findStr += fstr + ', ' is_date = 0 diff --git a/schemas/feedback.py b/schemas/feedback.py index 49ba4db..d3bc03e 100644 --- a/schemas/feedback.py +++ b/schemas/feedback.py @@ -5,5 +5,6 @@ from typing import List class Feedback(BaseModel): survey: dict # 存储的面试反馈 uid: str # 求职者唯一id + relevancy_id:str # survey数据 # {'voice':1,'thought':1,'diathesis':1,'evaluate':'评价','teacher_back':1} diff --git a/schemas/talentpool_filtrate.py b/schemas/talentpool_filtrate.py index fc343bf..2b1c667 100644 --- a/schemas/talentpool_filtrate.py +++ b/schemas/talentpool_filtrate.py @@ -3,11 +3,11 @@ from pydantic import BaseModel class Filtrate(BaseModel): user_id: str # 账号id - where: dict # 筛选项 + where: list # 筛选项 class Where(BaseModel): - where: dict # 筛选项 + where: list # 筛选项 class Where_list(BaseModel): diff --git a/schemas/user.py b/schemas/user.py index 9e25e17..cb6801a 100644 --- a/schemas/user.py +++ b/schemas/user.py @@ -69,7 +69,7 @@ class UserDB(DBBase): #email: EmailStr = None # 邮箱 is_superuser: bool = False name: str # 姓名 - nickname: str = '' + nickname: str tel: Any = '' last_login_ts: str = '尚未登录' data_where: dict = dict() diff --git a/utils/dingding.py b/utils/dingding.py index 1aa833a..0eef0ba 100644 --- a/utils/dingding.py +++ b/utils/dingding.py @@ -3,6 +3,7 @@ import datetime import json import pprint +import time from copy import deepcopy import pymongo @@ -63,7 +64,7 @@ def get_token(): return tokens -def get_uid(dept_id): +def get_uid1(dept_id): """ 获取钉钉部门的成员名和uid :return: @@ -193,7 +194,7 @@ def get_all_uid(): res['depid'] = depid[k] res_list = [] for i in v: - user_list = get_uid(i) + user_list = get_uid1(i) for nu in user_list: res_list.append(nu) res['user_id'] = res_list diff --git a/utils/func.py b/utils/func.py index ad77f61..8f3e390 100644 --- a/utils/func.py +++ b/utils/func.py @@ -502,7 +502,7 @@ def judge(**kwarg): jsontext = json.dumps(data) else: # 重启所有服务 run_task(data) - # 再添加这次的服务 + # 再添加这次的服务,单位秒 scheduler.enter(3600, 1, task, kwargs=kwarg) data[kwarg['uid']] = kwarg jsontext = json.dumps(data)