import operator import os import re from typing import Any from obs import ObsClient from copy import deepcopy import pandas as pd import pymongo from fastapi import APIRouter, Depends, Request, File, UploadFile from fastapi.security import OAuth2PasswordRequestForm from motor.motor_asyncio import AsyncIOMotorDatabase from api import deps # from utils.dingding import get_redis_alluid, send_dates,unionid,get_alluid_list from core import security from core.config import settings from core.security import get_password_hash from utils.dingding import * from utils.jianli import get_resume from utils.func import get_uid 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 datetime import timedelta from models.interview_zsgc import InterviewDo from utils import get_time, qujian_time, Download_xlsx, send_str_mail router = APIRouter() # 创建ObsClient实例 obsClient = ObsClient( access_key_id='UPEO770G619UPU8TU61Y', secret_access_key='M7zVRT1pjRtGSZ2TOZwKBRoVJLeWAOf633kHaNcu', server='obs.cn-east-2.myhuaweicloud.com' ) def chkData(data): res_data = [] for i in data.values(): res1 = deepcopy(i) if 'interview_type' in res1: key1 = res1['interview_type'] res1['interview_type'] = interview_type_dict.get(key1, '线下面试') if 'interview_sign' in res1: key2 = res1['interview_sign'] res1['interview_sign'] = interview_sign_dict.get(key2, '未签到') if 'feedback' in res1: key3 = res1['feedback'] res1['feedback'] = feedback_dict.get(key3, '未反馈') if 'interview_round' in res1: key4 = res1['interview_round'] res1['interview_round'] = interview_round_dict.get(key4, '初试') if 'interview_stage' in res1: key5 = res1['interview_stage'] res1['interview_stage'] = interview_stage_dict.get(key5, '初筛') if 'owner_name' in res1: key6 = res1['owner_name'] res1['owner_name'] = owner_name_dict.get(key6, '人才库') if 'education' in res1: key7 = res1['education'] res1['education'] = education_dict.get(key7, '大专') if 'mmended_state' in res1: key8 = res1['mmended_state'] res1['mmended_state'] = mmended_state_dict.get(key8, '未推荐') if 'interview_state' in res1: key9 = res1['interview_state'] res1['interview_state'] = interview_state_dict.get(key9, '待安排') if 'men_state' in res1: key10 = res1['men_state'] res1['men_state'] = men_state_dict.get(key10, '未反馈') if 'teacher_state' in res1: key11 = res1['teacher_state'] res1['teacher_state'] = teacher_state_dict.get(key11, '未反馈') if 'teacher_back' in res1: key12 = res1['teacher_back'] res1['teacher_back'] = teacher_back_dict.get(key12, '非常不满意') if 'offer_state' in res1: key13 = res1['offer_state'] res1['offer_state'] = offer_state_dict.get(key13, '未创建') if 'offer_exam_state' in res1: key14 = res1['offer_exam_state'] res1['offer_exam_state'] = offer_exam_state_dict.get(key14, '未发起') if 'notice_state' in res1: key15 = res1['notice_state'] res1['notice_state'] = notice_state_dict.get(key15, '未通知') if 'pass_why' in res1: key16 = res1['pass_why'] res1['pass_why'] = pass_why_dict.get(key16, '初筛') work_list = i['work_list'] if work_list: work_list = [eval(i1) for i1 in work_list] res1['work_list'] = work_list res_data.append(res1) return res_data # 面试查询 @router.post("/interview_find") async def interview_find( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据查询 """ await interview.init() res = interview.find_interview_sql() sql = res['sql'] data = await db.execute(sql) if not data: return schemas.Msg(code=-9, msg='无数据', data=None) return schemas.Msg(code=200, msg='ok', data=data) # 面试_主页初筛查询 @router.post("/interview_home_find") async def interview_home_find( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据主页初筛查询 """ await interview.init() res = interview.find_interview_home_sql() sql = res['sql'] data = await db.execute(sql) if not data: return schemas.Msg(code=-9, msg='无数据', data=None) return schemas.Msg(code=200, msg='ok', data=data) # 复筛查询 @router.post("/interview_screen_find") async def interview_screen_find( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据复筛查询 """ await interview.init() res = interview.find_interview_screen_sql() sql = res['sql'] data = await db.execute(sql) if not data: return schemas.Msg(code=-9, msg='无数据', data=None) return schemas.Msg(code=200, msg='ok', data=data) # 面试阶段查询 @router.post("/interview_exam_find") async def interview_exam_find( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据面试阶段查询 """ await interview.init() res = interview.find_interview_exam_sql() sql = res['sql'] data = await db.execute(sql) if not data: return schemas.Msg(code=-9, msg='无数据', data=None) return schemas.Msg(code=200, msg='ok', data=data) # offer阶段查询 @router.post("/interview_stage_num") async def interview_stage_num( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据offer阶段查询 """ await interview.init() res = interview.find_stage_num_sql() sql = res['sql'] data = await db.execute(sql) res_data = { '1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0, '9': 0, '10': 0, } if not data: return schemas.Msg(code=-9, msg='无数据', data=res_data) for i in data.values(): key = str(i['interview_stage']) if key not in res_data: continue res_data[key] = i['value'] return schemas.Msg(code=200, msg='ok', data=res_data) # 待入职阶段查询 @router.post("/interview_waite_in_find") async def interview_waite_in_find( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据待入职阶段查询 """ await interview.init() res = interview.find_interview_waite_in_sql() sql = res['sql'] data = await db.execute(sql) if not data: return schemas.Msg(code=-9, msg='无数据', data=[]) # 格式化数据 resdata = chkData(data) return schemas.Msg(code=200, msg='ok', data=resdata) # 面试修改 @router.post("/interview_update") async def interview_update( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据更新 """ await interview.init() res = interview.update_interview_sql() sql = res['sql'] try: data = await db.execute(sql) except: return schemas.Msg(code=-9, msg='数据有误', data=None) return schemas.Msg(code=200, msg='ok', data=data) # 写入面试数据 @router.post("/interview_insert") async def interview_insert( request: Request, interview: InterviewDo = Depends(InterviewDo), db: CKDrive = Depends(get_ck_db), ) -> schemas.Msg: """ interview面试数据写入 """ await interview.init() res = interview.insert_interview_sql() sql = res['sql'] insert_data = res['insert_data'] data = await db.execute_dict(sql, insert_data) return schemas.Msg(code=200, msg='ok', data=data) # 转存简历到华为云 @router.post("/file_to_hw") async def file_to_hw( request: Request, file: UploadFile = File(...), db: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """ 简历上传到华为云 """ path_data = os.getcwd() + '/jianli' # 当前文件所在的目录 if not os.path.exists(path_data): os.makedirs(path_data) contents = await file.read() filename = file.filename try: with open(path_data + '/' + filename, "wb") as f: # 将获取的file文件内容,写入到新文件中 f.write(contents) f.close() except: return schemas.Msg(code=400, msg='上传文件有误', data=None) try: res = obsClient.putFile('legu-cdn-source', 'hrms/' + filename, path_data + '/' + filename) if res.status < 300: # 地址 url = res.body.objectUrl # 简历初始文档 data_mode = { "interview_name": "", "interview_type": 1, "interview_sign": 0, "hope_money": "", "feedback": 0, "interview_round": 0, "event_time": datetime.now(), "name": "", "phone": "", "job_name": "", "hr_name": "", "work_exp": 0, "interview_stage": 1, "owner_name": 2, "education": 1, "work_undergo": [], "project_undergo": [], "work_list": [], "school": "", "at_school": "", "specialty": "", "specialty_do": [], "mmended_state": 0, "mail": "", "account": "", "id_card": "", "gender": "", "age": 0, "gam": "", "interview_state": 1, "counts": 1, "nation": "汉", "review": [], "upgrade": [], "come_time": "", "now_money": "", "men_state": 1, "teacher_state": 1, "teacher_back": 1, "offer_state": 1, "offer_exam_state": 1, "notice_state": 1, "pass_why": 0, "pass_text": [], "file_url": url, } uid = get_uid() data_mode['uid'] = uid sql = f"insert into HR.resumes(interview_name, interview_type, interview_sign, hope_money, feedback," \ f" interview_round, event_time, uid, name, phone, job_name, hr_name, work_exp, interview_stage, owner_name," \ f" education, work_undergo, project_undergo, work_list, school, at_school, specialty, specialty_do, " \ f"mmended_state, mail, account, id_card, gender, age, gam, interview_state, counts, nation, come_time," \ f" review, upgrade, now_money, men_state, teacher_state, teacher_back, offer_state, offer_exam_state," \ f" notice_state, pass_why, pass_text, file_url) values" # 存数据 await db.execute_dict(sql, [data_mode]) resData = {'file_url': url, 'filename': 'hrms/' + filename, 'uid': uid} return schemas.Msg(code=0, msg='ok', data=resData) else: print('errorCode:', res.errorCode) print('errorMessage:', res.errorMessage) return schemas.Msg(code=400, msg='上传华为云失败', data=None) except: import traceback print(traceback.format_exc()) return schemas.Msg(code=400, msg='上传华为云失败', data=None) # 导入面试数据 @router.post("/interview_file_insert") async def interview_file_insert( request: Request, data_in: schemas.Filenames, ) -> schemas.Msg: """ interview面试数据导入 """ path_data = os.getcwd() + '/jianli' # 当前文件所在的目录 if not os.path.exists(path_data): os.makedirs(path_data) filename = data_in.filenames.split('/')[-1] try: res = obsClient.getObject('legu-cdn-source', data_in.filenames, path_data + '/' + filename) if res.status < 300: data = get_resume(filename, path_data) education = data['education'] # 学历int转化 education_int = { '大专': 1, '本科': 2, '研究生': 3, '博士': 4, '硕士': 5, } if education and isinstance(education, str): data['education'] = education_int.get(education, 1) age = data['age'] if not age: data['age'] = 20 # 年龄int转化 if age and isinstance(age, str): true_age = re.search(r"\d+\.?\d*", age) if len(true_age.group()) > 2: data['age'] = 20 else: data['age'] = int(true_age.group()) work_exp = data['work_exp'] if not work_exp: data['work_exp'] = 0 # 工作经验float转化 if work_exp and isinstance(work_exp, str): true_work_exp = re.search(r"\d+\.?\d*", work_exp) if len(true_work_exp.group()) > 3: data['work_exp'] = 0 else: data['work_exp'] = float(true_work_exp.group()) print(data) # 项目切割 true_upgrade = [] if data['project_undergo']: string = data['project_undergo'][0] project_u = string.split('项目名') for chkstr in project_u: if ':' not in chkstr: continue chkdict = {} chklist = chkstr.split('\n\n') for turestr in chklist: turestr.strip() if not turestr: continue if turestr.startswith('称'): turestr1 = '项目名' + turestr chklist1 = turestr1.split('\n') chklist += chklist1 continue true_d_list = turestr.split(':') if len(true_d_list) == 2: chk_list = deepcopy(true_d_list) chkdict[chk_list[0]] = chk_list[1] true_dict = deepcopy(chkdict) true_upgrade.append(true_dict) work_list = data['work_list'] true_work = [] if work_list: for dstr in work_list: data1 = eval(dstr) dictdata = deepcopy(data1) true_work.append(dictdata) res_data = { 'data': data, 'project_undergo': true_upgrade, 'work_list': true_work } return schemas.Msg(code=200, msg='ok', data=res_data) else: return schemas.Msg(code=-9, msg='解析失败', data='') except: return schemas.Msg(code=-9, msg='解析失败', data='') @router.post("/add_job") async def add_job( request: Request, data_in: schemas.Ins_Job, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """新增职位""" await crud.jobs.insert_job(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.post("/condition") async def condition( request: Request, data_in: schemas.Interview, ckdb: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """ 面试情况 """ res = data_in.date strs = [] for k, v in res.items(): if v != '': if 'int' in str(type(v)): str_s = f"{k} = {v}" strs.append(str_s) else: str_s = f"{k} = '{v}'" strs.append(str_s) where = ' and '.join(strs) # 当前日期 times = get_time() # 今天的面试 if data_in.time_type == 'now': # 查询返回的数据一共多少条 len_sql = f"""select uid from HR.resumes where {where} and toDate(star_time) == '{times}' ORDER BY event_time""" sql = f"""select interview_round,interview_type,star_time,end_time,name,phone,job_names,hr_name,uid,interview_id, feedback,interview_name from HR.resumes where {where} and toDate(star_time) == '{times}' ORDER BY event_time LIMIT 10 OFFSET {(data_in.pages - 1) * 10}""" # 明天及之后的面试 elif data_in.time_type == 'tomorrow': len_sql = f"""select uid from HR.resumes where {where} and toDate(star_time) > '{times}' ORDER BY event_time""" sql = f"""select interview_round,interview_type,star_time,end_time,name,phone,job_names,hr_name,uid,interview_id, feedback,interview_name from HR.resumes where {where} and toDate(star_time) > '{times}' ORDER BY event_time LIMIT 10 OFFSET {(data_in.pages - 1) * 10}""" # 昨天及以前的面试 else: len_sql = f"""select uid from HR.resumes where {where} and toDate(star_time) < '{times}' ORDER BY event_time""" sql = f"""select interview_round,interview_type,star_time,end_time,name,phone,job_names,hr_name,uid,interview_id, feedback,interview_name from HR.resumes where {where} and toDate(star_time) < '{times}' ORDER BY event_time LIMIT 10 OFFSET {(data_in.pages - 1) * 10}""" if where == '': len_sql = len_sql.replace('where and', 'where', 1) sql = sql.replace('where and', 'where', 1) # 返回数据条数 df_len = await ckdb.query_dataframe(len_sql) len_date = len(df_len) df = await ckdb.query_dataframe(sql) if df.empty: data = {'lens': 0, 'data': [] } return schemas.Msg(code=-9, msg='无数据', data=data) datas = [] for i in range(len(df)): dates = {} dates['key'] = df['uid'][i] date = {} # 面试信息 date['interview_round'] = int(df['interview_round'][i]) date['interview_type'] = int(df['interview_type'][i]) noe = str(df['end_time'][i]).split(' ')[-1] timess = str(df['star_time'][i]) + '~' + noe date['time'] = timess dates['msg'] = date dates['name'] = df['name'][i] dates['phone'] = df['phone'][i] dates['job_names'] = df['job_names'][i] dates['hr_name'] = df['hr_name'][i] date1 = {} date1['type'] = int(df['feedback'][i]) date1['name'] = df['interview_name'][i] dates['type'] = date1 dates['interview_id'] = df['interview_id'][i] datas.append(dates) data = {'lens': len_date, 'data': datas } return schemas.Msg(code=200, msg='ok', data=data) @router.post("/get_job") async def get_job( request: Request, data_in: schemas.Jobs = None, db: AsyncIOMotorDatabase = Depends(get_database), ckdb: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """获取职位名称""" # 获取对应条件的职位 res = await crud.jobs.all_fields(db, data_in) # 获取职位数量 nums = len(res) job = [] for i in res: # 获取职位名称 job_list = {} job_list['key'] = i['job_id'] # 职位id # 查询对应职位id入职多少人 sql = f""" select count(job_id) as nu from HR.resumes where job_id = '{i['job_id']}' and interview_stage = 7 """ num = await ckdb.execute(sql) # 候选人总数 sql1 = f""" select count(job_id) as nu from HR.resumes where job_id = '{i['job_id']}' and interview_stage < 6 """ hou_num = await ckdb.execute(sql1) job_list['job_name'] = i['job_name'] # 职位名 job_list['principal'] = i['principal'] # 招聘负责人 job_list['job_sector'] = i['job_sector'] # 部门 job_list['job_num'] = i['job_num'] # 目标招聘人数 job_list['now_job_num'] = num[0]['nu'] # 对应职位的入职人数 job_list['hou_num'] = hou_num[0]['nu'] # 候选人总数 job.append(job_list) data = { 'num': nums, 'job': job } return schemas.Msg(code=200, msg='ok', data=data) @router.post("/download_interview") async def download_interview( request: Request, data_in: schemas.Timesinter, ckdb: CKDrive = Depends(get_ck_db)): """导出所有面试安排""" sql = f"""SELECT interview_type,interview_stage,star_time,end_time,name,phone,job_name,hr_name,interview_name, interview_sign FROM HR.resumes WHERE toDate(star_time) >= '{data_in.start_time}' and toDate(star_time) <= '{data_in.end_time}'""" df = await ckdb.query_dataframe(sql) if df.empty: return schemas.Msg(code=-9, msg='无数据', data='') # xlsx表名 xlsx_name = data_in.start_time + '~' + data_in.end_time + '(包含起止日)' datas = [] for i in range(len(df)): one_data = [] one_data.append(interview_type_dict[df['interview_type'][i]]) one_data.append(interview_stage_dict[df['interview_stage'][i]]) df_time = qujian_time(df['star_time'][i], df['end_time'][i]) one_data.append(df_time) one_data.append(df['name'][i]) one_data.append(df['phone'][i]) one_data.append(df['job_name'][i]) one_data.append(df['hr_name'][i]) one_data.append(df['interview_name'][i]) one_data.append(interview_sign_dict[df['interview_sign'][i]]) datas.append(one_data) columns = ['面试类型', '面试阶段', '面试时间', '候选人', '联系方式', '应聘职位', '面试负责人', '面试官', '面试签到'] dfmi = pd.DataFrame(data=datas, columns=columns) Download = Download_xlsx(dfmi, xlsx_name) return Download @router.post("/add_remark") async def add_remark( request: Request, data_in: schemas.BaseRemark, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """添加备注""" await crud.api_interview_remark.insert_remark(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.post("/find_remark") async def find_remark( request: Request, data_in: schemas.FindRemark, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """查找备注""" data = await crud.api_interview_remark.get_interview_remarks(db, data_in) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/find_remark") async def find_remark( request: Request, data_in: schemas.FindRemark, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """查找备注""" data = await crud.api_interview_remark.get_interview_remarks(db, data_in) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/find_criterion") async def find_criterion( request: Request, data_in: schemas.get_uids, ckdb: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """获取标准版简历""" # sql = f""" # select name,phone,job_name,work_exp,owner_name,education,work_undergo,school,specialty, # graduate_time,mail,account,id_card,gender,nation,age,at_school,specialty_do,hope_money,resume_affix_id, # review,work_list,project_undergo,upgrade,come_time,now_money,work_in_time from HR.resumes WHERE uid = '{data_in.uid}' # """ sql = f""" select * from HR.resumes WHERE uid = '{data_in.uid}' """ df = await ckdb.query_dataframe(sql) data = {} column = df.columns for i in column: if 'int' in str(type(df[i][0])): data[i] = int(df[i][0]) else: data[i] = df[i][0] return schemas.Msg(code=200, msg='ok', data=data) @router.post("/resume_affix") async def resume_affix( request: Request, data_in: schemas.Post_uid, ckdb: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """保存附件id""" sql = f""" ALTER table HR.resumes update resume_affix_id = {data_in.resume_affix_id} WHERE uid = '{data_in.uid}' """ await ckdb.execute(sql) return schemas.Msg(code=200, msg='ok', data='') @router.post("/updata_entry") async def updata_entry( request: Request, data_in: schemas.Entry, ckdb: CKDrive = Depends(get_ck_db), db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """修改入职状态""" sql = f""" ALTER table HR.resumes update interview_stage = {data_in.interview_stage} WHERE uid = '{data_in.uid}' """ await ckdb.execute(sql) # 给招聘中职位计入职数 res = await crud.jobs.find_job(db, data_in.job_id) num = res['now_job_num'] + 1 await crud.jobs.update_job(db, schemas.Jobs(job_id=data_in.job_id, now_job_num=num)) return schemas.Msg(code=200, msg='ok', data='') @router.post("/get_str_mail") async def get_str_mail( request: Request, data_in: schemas.Email_str, ckdb: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """获取邮件文本""" data = f""" {data_in.name},您好\n\n感谢关注乐谷在线科技有限公司!很高兴的通知您通过了我们的面试,真诚的邀请您加入我们的团队\n职位:{data_in.job}\n入职时间:{data_in.times} \n薪酬:{data_in.money}\n联系人:{data_in.hr_name}\n联系电话:{data_in.phone}\n联系邮箱:{data_in.email}\n\n如有问题请用以上联系方式及时与我们沟通,谢谢!\n(系统邮件,请勿回复) """ return schemas.Msg(code=200, msg='ok', data=data) @router.post("/send_str_mail") async def send_mail( request: Request, data_in: schemas.send_str_mail, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """发送邮件""" try: # 发送邮件 send_str_mail(data_in.email_str, data_in.email) # 保存发送邮件的记录 now_time = str(datetime.now()).split('.')[0] await crud.email_record.create(db, schemas.email_record(user_id=data_in.user_id, text=data_in.email_str, times=now_time, name=data_in.name, state=1, read_status=0, type='email')) return schemas.Msg(code=200, msg='邮件发送成功', data='') except Exception: now_time = str(datetime.now()).split('.')[0] await crud.email_record.create(db, schemas.email_record(user_id=data_in.user_id, text=data_in.email_str, times=now_time, name=data_in.name, state=0, read_status=0, type='email')) return schemas.Msg(code=200, msg='邮件发送失败', data='') @router.post("/email_record") async def email_record( request: Request, data_in: schemas.get_email_record, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """获取发送邮件的记录""" data = await crud.email_record.all_record(db, data_in) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/operate_log") async def operate_log( request: Request, data_in: schemas.operate_log, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """同步插入操作记录""" await crud.operate_log.create(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.post("/get_operate_log") async def get_operate_log( request: Request, data_in: schemas.get_operate_log, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """获取操作记录""" data = await crud.operate_log.all_log(db, data_in) # 对时间进行排序 data = sorted(data, key=operator.itemgetter('times')) return schemas.Msg(code=200, msg='ok', data=data) @router.get("/get_dding_user") async def get_dding_user( request: Request, ) -> schemas.Msg: """获取钉钉的用户id""" data = get_redis_alluid() return schemas.Msg(code=200, msg='ok', data=data) @router.post("/teacher_state") async def teacher_state( request: Request, data_in: schemas.user_id, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """催促面试官反馈功能""" # 同步钉钉发消息给面试官 try: now_time = str(datetime.now()).split('.')[0] content = f"【催促反馈】\n请面试官尽快给{data_in.name}做面试反馈\n提醒时间:{now_time}" send_dates(content, data_in.user_id) return schemas.Msg(code=200, msg='发送成功', data='') except Exception: return schemas.Msg(code=-9, msg='发送失败', data='') @router.post("/add_mode") async def add_mode( request: Request, data_in: schemas.InsertModes, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """添加hr分组""" await crud.api_interview_modes.insert_modes(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.post("/find_mode") async def find_mode( request: Request, data_in: schemas.FindModes, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """查找hr所有分组""" data = await crud.api_interview_modes.get_interview_modes(db, data_in) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/update_mode") async def update_mode( request: Request, data_in: schemas.UpdateModes, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """更新一条hr分组数据""" await crud.api_interview_modes.update_modes(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.get("/name") async def name( request: Request, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """获取所有用户角色""" res = await crud.user.get_all_users(db, {}) data = [] for i in res: data_dict = {} data_dict['_id'] = i.get('_id') data_dict['name'] = i.get('name') data_dict['user_id'] = i.get('user_id') data_dict['email'] = i.get('email') data_dict['rank'] = i.get('rank') # 用于区分是面试官还是hr data.append(data_dict) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/amend_job") async def amend_job( request: Request, data_in: schemas.Jobs, db: AsyncIOMotorDatabase = Depends(get_database), ) -> schemas.Msg: """修改职位信息,修改职位招聘状态""" await crud.jobs.update_job(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.post("/create") async def create( request: Request, data_in: schemas.DashboardCreate, db: AsyncIOMotorDatabase = Depends(get_database), current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """创建看板""" try: await crud.dashboard.create(db, data_in.name, user_id=current_user.id) except pymongo.errors.DuplicateKeyError: return schemas.Msg(code=-1, msg='看板已存在', data='看板已存在') return schemas.Msg(code=200, msg='ok', data='创建成功') @router.post("/delete") async def delete( request: Request, data_in: schemas.DashboardDelete, db: AsyncIOMotorDatabase = Depends(get_database), current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """删除看板""" del_dashboard = await crud.dashboard.delete(db, {'_id': {'$in': data_in.ids}}) if del_dashboard.deleted_count == 0: return schemas.Msg(code=-1, msg='error', data='删除失败') return schemas.Msg(code=200, msg='ok', data='删除成功') @router.post("/get_dashboard") async def get_dashboard(request: Request, data_in: schemas.ReadDashboard, db: AsyncIOMotorDatabase = Depends(get_database), current_user: schemas.UserDB = Depends(deps.get_current_user) ): """获取一个看板""" res = await crud.dashboard.get(db, id=data_in.id) reports = {item['report_id']: item for item in res['reports']} reports_detail = await crud.report.find_many(db, {'_id': {'$in': list(reports.keys())}}, {'query.cachedata': False}) for item in reports_detail: reports[item['_id']].update(item) return schemas.Msg(code=200, msg='ok', data='') @router.post("/edit") async def edit( request: Request, data_in: schemas.EditDashboard, db: AsyncIOMotorDatabase = Depends(get_database), current_user: schemas.UserDB = Depends(deps.get_current_user) ): """编辑看板名""" await crud.dashboard.update_one(db, {'_id': data_in.dashboard_id}, {'$set': {'name': data_in.new_name}}) return schemas.Msg(code=200, msg='ok', data='') @router.post("/notarize") async def notarize( request: Request, data_in: schemas.Notarize, ckdb: CKDrive = Depends(get_ck_db), db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """简历确认进入面试阶段""" sql = f""" ALTER table HR.resumes update interview_state = 2,hr_name = '{data_in.hr_name}',hr_id = '{data_in.hr_id}',interview_name = '{data_in.interview_name}',interview_id = '{data_in.interview_id}' WHERE uid = '{data_in.uid}' """ await ckdb.execute(sql) find_sql = f""" select uid,name,interview_name,hr_name,star_time,interview_sign,job_id,job_names,mail from HR.resumes where uid = '{data_in.uid}' """ df = await ckdb.query_dataframe(find_sql) # 存份面试数据到mongodb now_time = str(datetime.now()).split('.')[0] await crud.interview_record.insert_record(db, schemas.interview_record(uid=df['uid'][0], # 唯一id name=df['name'][0], # 求职者姓名 interview_name=df['interview_name'][0], # 面试官姓名 hr_name=df['hr_name'][0], # hr姓名 star_time=df['star_time'][0], # 开始面试时间 interview_sign=0, # 签到状态 job_id=df['job_id'][0], # 我们自己招聘的职位id job_names=df['job_names'][0], # 我们自己招聘的职位名 times=now_time, # 创建数据日期 read_status=0, # 读取状态 type='interview' # 记录的类型 )) if df['mail'][0] != '': # 发送邮件给面试者通知面试 msg = f"""{df['name'][0]},您好\n\n感谢关注乐谷在线科技有限公司!请于{df['star_time'][0]}到公司参见面试。\n联系人:{data_in.hr_name}\n联系电话:{data_in.hr_phone}\n联系邮箱:{ data_in.hr_email}\n\n如有问题请用以上联系方式及时与我们沟通,谢谢!\n(系统邮件,请勿回复) """ send_str_mail(msg, df['mail'][0]) return schemas.Msg(code=200, msg='ok', data='') @router.post("/alter") async def alter( request: Request, data_in: schemas.Stage, ckdb: CKDrive = Depends(get_ck_db), db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """更改简历阶段""" if data_in.stage == 1: # 初筛 sql = f""" ALTER table HR.resumes update interview_stage = 1,job_id = '{data_in.data['job_id']}',job_names = '{data_in.data['job_names']}' WHERE uid = '{data_in.uid}' """ else: sql = f""" ALTER table HR.resumes update interview_stage = {data_in.stage} WHERE uid = '{data_in.uid}' """ await ckdb.execute(sql) return schemas.Msg(code=200, msg='ok', data='') @router.post("/get_report") async def get_report( request: Request, data_in: schemas.Findreport, ckdb: CKDrive = Depends(get_ck_db), db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """获得已添加的报表""" # 获取自己的报表 res = await crud.dashboard.find_report(db, user_id=data_in.report_id) return schemas.Msg(code=200, msg='ok', data=res) @router.post("/create_report") async def create_report( request: Request, data_in: schemas.ReportCreate, ckdb: CKDrive = Depends(get_ck_db), db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """新建报表""" try: await crud.report.create(db, data_in) except pymongo.errors.DuplicateKeyError: return schemas.Msg(code=-9, msg='error', data='报表已存在') return schemas.Msg(code=200, msg='创建成功', data='') @router.post("/up_report") async def up_report( request: Request, data_in: schemas.ReportEdit, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """编辑报表""" await crud.report.update_one(db, {'_id': data_in.report_id}, {'$set': {'query': data_in.query, 'name': data_in.name, 'desc': data_in.desc}}) # 只能报表所有者编辑 # res = await crud.report.update_one(db, {'_id': data_in.report_id, 'user_id': request.user.id}, # {'$set': {'query': data_in.query, 'name': data_in.name, 'desc': data_in.desc}}) # if not res.matched_count: # #if res.matched_count: # return schemas.Msg(code=-1, msg='只能报表所有者编辑') return schemas.Msg(code=200, msg='编辑成功', data='') @router.post("/edit_report") async def edit_report(request: Request, data_in: schemas.EditReport, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """看板样式设置""" await crud.dashboard.update_one(db, {'_id': data_in.id, 'reports.report_id': data_in.report.report_id}, {'$set': {f'reports.$.{k}': v for k, v in data_in.report.dict(skip_defaults=True).items()}}) return schemas.Msg(code=200, msg='ok', data='') @router.post("/head") async def head( request: Request, data_in: schemas.Post_head, ckdb: CKDrive = Depends(get_ck_db) ) -> schemas.Msg: """保存头像链接""" sql = f""" ALTER table HR.resumes update head = '{data_in.head_id}' WHERE uid = '{data_in.uid}' """ await ckdb.execute(sql) return schemas.Msg(code=200, msg='ok', data='') @router.get("/hint") async def hint( request: Request, data_in: schemas.Get_hr, db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """重要事项-面试相关""" # 邮件,反馈 res = await crud.email_record.all_hint(db) # 面试记录 interview = await crud.interview_record.all_fields(db, {'hr_name': data_in.hr_name}) for i in interview: res.append(i) data = sorted(res, key=operator.itemgetter('times')) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/up_hint") async def up_hint( request: Request, data_in: schemas.Up_hint, ckdb: CKDrive = Depends(get_ck_db), db: AsyncIOMotorDatabase = Depends(get_database) ) -> schemas.Msg: """批量修改已读状态""" # 面试记录 if data_in.type == 'interview': await crud.interview_record.up_interview(db, data_in) # 邮件,反馈 else: await crud.email_record.up_hint(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.post("/login") async def login( data_in: schemas.Login, data: OAuth2PasswordRequestForm = Depends(), db: AsyncIOMotorDatabase = Depends(get_database) ) -> Any: """ OAuth2兼容令牌登录,获取将来令牌的访问令牌 """ user_id = Unionid(data_in.unionid) user_list = get_alluid_list() if user_id not in user_list: return schemas.Msg(code=-1, msg='密码或用户名错误') user = await crud.user.gets_user(db, user_id=user_id) if user.state == 1: return schemas.Msg(code=-1, msg='您的账号已被锁定,请联系管理员解锁') access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) await crud.user.update_login_time(db, user.id) # 更新最后一次登录时间 return { 'data': { 'name': user.name, # 名字 'email': user.email, # 邮箱 'tel': user.tel, # 电话 'user_id': user.id, # 钉钉id 'rank': user.rank, # 区分hr和面试官 'token': security.create_access_token( expires_delta=access_token_expires, user_id=user.user_id, email=user.email, tel=user.tel, name=user.name), "token_type": "bearer"}, 'access_token': security.create_access_token( expires_delta=access_token_expires, user_id=user.user_id, email=user.email, tel=user.tel, name=user.name ), "token_type": "bearer", 'code': 200, 'msg': 'success', } @router.post("/reset_password") async def reset_password(request: Request, data_in: schemas.UserRestPassword, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.User = Depends(deps.get_current_user) ) -> Any: """ 修改其他人密码 """ try: await crud.user.reset_password(db, data_in) except Exception as e: return schemas.Msg(code=-9, msg='修改失败', data={'username': data_in}) return schemas.Msg(code=200, msg='ok') @router.post("/reset_my_password") async def reset_my_password(request: Request, data_in: schemas.UserRestMyPassword, db: AsyncIOMotorDatabase = Depends(get_database), current_user: schemas.User = Depends(deps.get_current_user) ) -> Any: """ 修改自己的密码 """ await crud.user.reset_password(db, schemas.UserRestPassword(user_id=current_user.user_id, password=data_in.password)) return schemas.Msg(code=200, msg='ok') @router.post("/add_account") async def add_account( request: Request, data_in: schemas.Createuser, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.User = Depends(deps.get_current_user) ) -> schemas.Msg: """ 创建新账号 """ user_id = Unionid(data_in.unionid) user_list = get_alluid_list() if user_id not in user_list: return schemas.Msg(code=-9, msg="不是本公司的员工") if is_exists := await crud.user.exists(db, {'user_id': user_id}): return schemas.Msg(code=-9, msg='已创建该账号') else: new_account = schemas.UserCreate(name=data_in.name, hashed_password=get_password_hash('123'), unionid=data_in.unionid, rank=data_in.rank, email=data_in.email, tel=data_in.tel, user_id=user_id) await crud.user.create(db, new_account) # 创建账号 return schemas.Msg(code=200, msg='创建成功', data='') @router.post("/forbid_login") async def forbid_login(request: Request, data_in: schemas.Get_userid, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.User = Depends(deps.get_current_user) ) -> schemas.Msg: """ 禁止/解禁用户登录功能 """ if data_in.type == 1: await crud.user.forbid_lojin(db, data_in, 1) elif data_in.type == 0: await crud.user.forbid_lojin(db, data_in, 0) return schemas.Msg(code=200, msg='ok', data='') @router.post("/owner_list") async def owner_list( request: Request, data_in: schemas.Getdate, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """获取基本信息列表""" try: res = await crud.basic_data.one_owner(db, data_in) except Exception as e: return schemas.Msg(code=-9, msg='查无数据', data='') return schemas.Msg(code=200, msg='ok', data=res) @router.post("/owner_edit") async def owner_edit( request: Request, data_in: schemas.Ownername, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """新增,删除基本信息""" await crud.basic_data.update(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.get("/get_section") async def get_section( request: Request, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """获取对应部门及职位""" res = await crud.section.get_all(db) return schemas.Msg(code=200, msg='ok', data=res) @router.post("/ins_section") async def get_section( request: Request, data_in: schemas.Ins_section, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """新增对应部门及职位""" await crud.section.ins_section(db, data_in) return schemas.Msg(code=200, msg='ok', data='') @router.get("/api_list") async def api_list( request: Request, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """ 所有的api """ re = await crud.api_module.get_api_module(db) res = [] for i in re: if i['path_name'] != 'root': i['_id'] = str(i['_id']) res.append(i) return schemas.Msg(code=200, msg='ok', data=res) @router.post("/alter_api_module") async def add_policy( request: Request, data_in: schemas.Add_module, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ): """修改api_module权限状态""" res = await crud.api_module.get_one_module(db, data_in) for i in range(len(res['state'])): if data_in.url == res['api_list'][i]: if data_in.types == False: res['state'][i] = False else: res['state'][i] = True await crud.api_module.update_one_module(db, res) return schemas.Msg(code=200, msg='修改成功', data='') @router.get("/api_module") async def domain_list( request: Request, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """ 角色管理创建角色时显示的各个模块 """ res = await crud.api_module.get_api_module(db) api_module = [] for i in res: if i['path_name'] != 'root': data = [] data.append(i['auth_id']) data.append(i['path_name']) api_module.append(data) return schemas.Msg(code=200, msg='ok', data=api_module) @router.post("/add_api") async def add_api( request: Request, data_in: schemas.AddApi, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """ '在api_module'添加api """ res = await crud.api_module.get_api_module(db) for i in res: # 判断路由是否存在 if data_in.path in i['api_list']: return schemas.Msg(code=200, msg='该路由已存在', data='') path_list = [] for i in res: path_list.append(i['path_name']) if data_in.name in path_list: # 在原有的基础上添加路由 for i in res: if data_in.name == i['path_name']: i['api_list'].append(data_in.path) i['api_name'].append(data_in.desc) i['state'].append(True) await crud.api_module.updata_quanxian_module(db, schemas.Url_module(auth_id=i['auth_id'], path_name=data_in.name, api_list=i['api_list'], api_name=i['api_name'], state=i['state'])) return schemas.Msg(code=200, msg='ok', data='路由添加成功!') else: # 另外添加新的权限模块 auth_list = [] for i in res: auth_list.append(i['auth_id']) auth_id = max(auth_list) auth_id = 'abc' + str(int(auth_id.split('c')[-1]) + 1) await crud.api_module.insert_quanxian(db, schemas.Url_module(auth_id=auth_id, path_name=data_in.name, api_list=[data_in.path], api_name=[data_in.desc], state=[True])) return schemas.Msg(code=200, msg='ok', data='路由添加成功!') @router.post("/add_policy") async def add_policy( request: Request, data_in: schemas.Datalist, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ): """ 向当前权限添加新路由 """ res = await crud.url_list.find_one_url(db, data_in) for i in range(len(res['api_list'])): if res['api_list'][i] == data_in.path: res['state'][i] = True await crud.url_list.update_url_url(db, res) return schemas.Msg(code=200, msg='修改成功', data='') @router.post("/del_policy") async def remove_policy( request: Request, data_in: schemas.Del_role, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ): """ 修改角色api权限 """ res = await crud.url_list.find_one_url(db, data_in) for i in range(len(res['api_list'])): if res['api_list'][i] == data_in.path: res['state'][i] = False await crud.url_list.update_url_url(db, res) return schemas.Msg(code=200, msg='修改成功', data='') @router.get("/roles") async def roles( request: Request, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """ 获取所有的管理员用户 """ res = await crud.url_list.get_all(db) role = [] data = [] # 区分不同项目下的权限用户 for i in res: if i['system'] == 1 and i['name'] != 'root': role.append(i['name']) # 得到不同权限用户 role = list(set(role)) for id in role: data_dcit = {} data_dcit['name'] = id auth_id = [] system = [] data_list = [] for i in res: if i['name'] == id: data_one = {} auth_id.append(i['auth_id']) system.append(i['system']) data_one['path_name'] = i['path_name'] data_one['api_name'] = i['api_name'] data_one['api_list'] = i['api_list'] data_one['state'] = i['state'] data_list.append(data_one) data_dcit['datalist'] = data_list data_dcit['auth_id'] = auth_id[0] data_dcit['system'] = system[0] data.append(data_dcit) return schemas.Msg(code=200, msg='ok', data=data) @router.post("/add_roles") async def add_roles( request: Request, data_in: schemas.Add_role, db: AsyncIOMotorDatabase = Depends(get_database), # current_user: schemas.UserDB = Depends(deps.get_current_user) ) -> schemas.Msg: """ 创建不同权限角色 """ res = await crud.url_list.get_all(db) for i in res: # 判断创建的角色是否已经存在 if data_in.system == 1: if data_in.name == i['name']: return schemas.Msg(code=200, msg='该角色已存在!') else: if data_in.name == i['name']: return schemas.Msg(code=200, msg='该角色已存在!') auth = [] # 系统默认权限角色 if data_in.system == 1: for i in res: auth.append(i['auth_id']) max_auth = 'ab' + str(int(max(auth).split('b')[-1]) + 1) api_module = await crud.api_module.get_api_module(db) for i in api_module: if i['auth_id'] in data_in.path_name: await crud.url_list.insert_url(db, schemas.Url_list(name=data_in.name, auth_id=max_auth, path_name=i['path_name'], api_list=i['api_list'], api_name=i['api_name'], state=i['state'], system=data_in.system)) else: state = [] for nu in range(len(i['state'])): state.append(False) if i['path_name'] != 'root': await crud.url_list.insert_url(db, schemas.Url_list(name=data_in.name, auth_id=max_auth, path_name=i['path_name'], api_list=i['api_list'], api_name=i['api_name'], state=state, system=data_in.system)) return schemas.Msg(code=200, msg='添加角色成功', data='') else: # 系统其他权限角色 for i in res: auth.append(i['auth_id']) max_auth = 'ab' + str(int(max(auth).split('b')[-1]) + 1) api_module = await crud.api_module.get_api_module(db) for i in api_module: if i['auth_id'] in data_in.path_name: await crud.url_list.insert_urls(db, schemas.Url_lists(name=data_in.name, auth_id=max_auth, path_name=i['path_name'], api_list=i['api_list'], api_name=i['api_name'], state=i['state'], system=data_in.system)) else: state = [] for nu in range(len(i['state'])): state.append(False) if i['path_name'] != 'root': await crud.url_list.insert_urls(db, schemas.Url_lists(name=data_in.name, auth_id=max_auth, path_name=i['path_name'], api_list=i['api_list'], api_name=i['api_name'], state=state, system=data_in.system)) return schemas.Msg(code=200, msg='添加角色成功', data='') @router.post("/add_role_domain") async def add_role_domain( request: Request, data_in: schemas.AddRoleForUsersInDomain, db: AsyncIOMotorDatabase = Depends(get_database), current_user: schemas.UserDB = Depends(deps.get_current_user)): """ 在当前项目为角色添加相应权限 """ res = await crud.url_list.get_all(db) role_id = {} for i in res: role_id[i['auth_id']] = i['name'] for item in data_in.data: now_quanxian = await crud.user_url.get_quanxian(db, schemas.Url_quanxian(user_id=item.role_id)) # 如果不存在该用户其他的权限,则新增一个 if now_quanxian == {}: await crud.user_url.insert_quanxian(db, schemas.Url_quanxian(user=item.username, user_id=item.role_id, quanxian=role_id[item.auth_id], quanxian_id=item.auth_id)) return schemas.Msg(code=200, msg='添加成功', data='') # 存在则在这个用户表示已经有权限 else: return schemas.Msg(code=-9, msg='权限已存在', data='')