From db6dcc91de3b5cde2bf1e9f99d01a5766e97c9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=80=C3=AE=C3=97=C3=9A=C3=95=C3=B1?= Date: Thu, 21 Jul 2022 17:06:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=A0=E9=81=93=E8=B4=A8=E9=87=8F,=E9=98=B6?= =?UTF-8?q?=E6=AE=B5=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api_v1/endpoints/forms.py | 126 +++++++++++++++++++++++++++- crud/crud_jobs.py | 9 +- models/interview_zsgc.py | 98 ++++++++++++++++++++-- 接口文档/候选人质量模板接口文档.txt | 5 +- 接口文档/渠道质量模板接口文档.txt | 53 ++++++++++++ 接口文档/职位阶段模板接口文档.txt | 46 ++++++++++ 6 files changed, 324 insertions(+), 13 deletions(-) create mode 100644 接口文档/渠道质量模板接口文档.txt create mode 100644 接口文档/职位阶段模板接口文档.txt diff --git a/api/api_v1/endpoints/forms.py b/api/api_v1/endpoints/forms.py index f35eab7..ed86548 100644 --- a/api/api_v1/endpoints/forms.py +++ b/api/api_v1/endpoints/forms.py @@ -2,6 +2,7 @@ import operator import os import re import pandas as pd +from copy import deepcopy from fastapi import APIRouter, Depends, Request, File, UploadFile from motor.motor_asyncio import AsyncIOMotorDatabase @@ -21,12 +22,12 @@ router = APIRouter() # 候选人质量报表 @router.post("/man_mass_form") -async def interview_find( +async def man_mass_form( 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'] @@ -171,7 +172,7 @@ async def interview_find( else: work_exp['20-40'].append(i_name) - i_job_name = interview_data.get('job_name', '') + i_job_name = interview_data.get('job_names', '') if i_job_name: if i_job_name in account: job_name[i_job_name].append(i_name) @@ -210,3 +211,122 @@ async def interview_find( return schemas.Msg(code=200, msg='ok', data=res_msg) + +# 职位阶段数据报表 +@router.post("/get_every_stage_form") +async def owner_form( + request: Request, + interview: InterviewDo = Depends(InterviewDo), + ck_db: CKDrive = Depends(get_ck_db), + db: AsyncIOMotorDatabase = Depends(get_database) +) -> schemas.Msg: + """ 职位阶段数据报表 """ + all_jobs = await crud.jobs.all_some_field(db) + res_msg = {} + job_id_to_name = {} + job_ids = [] + for job_data in all_jobs: + job_id = job_data['job_id'] + job_ids.append(job_id) + job_name = job_data['job_name'] + job_id_to_name[job_id] = job_name + res_job_data = deepcopy({k: v for k, v in job_data.items() if k != 'job_id'}) + res_job_data.update({ + '初筛': 0, + '复筛': 0, + '面试': 0, + 'offer': 0, + '待入职': 0, + '已入职': job_data['now_job_num'], + }) + res_msg[job_name] = res_job_data + + await interview.init() + res = interview.get_every_stage_form_sql(job_ids) + sql = res['sql'] + data = await ck_db.execute(sql) + for ck_data in data.values(): + # 职位id不存在跳过 + if ck_data['job_id'] not in job_id_to_name: + continue + ck_job_name = job_id_to_name[ck_data['job_id']] + stage = ck_data['interview_stage'] + if stage == 1: + res_msg[ck_job_name]['初筛'] += 1 + elif stage == 2: + res_msg[ck_job_name]['复筛'] += 1 + elif stage == 3: + res_msg[ck_job_name]['面试'] += 1 + elif stage == 4: + res_msg[ck_job_name]['offer'] += 1 + elif stage == 5: + res_msg[ck_job_name]['待入职'] += 1 + + return schemas.Msg(code=200, msg='ok', data=res_msg) + + +# 每个阶段报表 +@router.post("/get_owner_form") +async def owner_form( + request: Request, + interview: InterviewDo = Depends(InterviewDo), + db: CKDrive = Depends(get_ck_db), +) -> schemas.Msg: + """ 渠道质量报表 """ + await interview.init() + res = interview.get_owner_form_sql() + sql = res['sql'] + data = await db.execute(sql) + # 简历渠道 + owner_dict = {1: '前程无忧', 2: '人才库', 3: '智联招聘', 4: 'Boss直聘', 5: '58同城'} + chk_data = { + '前程无忧': [], + '人才库': [], + '智联招聘': [], + 'Boss直聘': [], + '58同城': [], + } + for i in data.values(): + owner_name = owner_dict[i['owner_name']] + i_data = deepcopy(i) + chk_data[owner_name].append(i_data) + + res_msg = { + '前程无忧': { + 'count': 0 + }, + '人才库': { + 'count': 0 + }, + '智联招聘': { + 'count': 0 + }, + 'Boss直聘': { + 'count': 0 + }, + '58同城': { + 'count': 0 + }, + } + + for key, data_list in chk_data.items(): + count_num = len(data_list) + offer_num = len([1 for i in data_list if i['interview_stage'] >= 5]) + work_num = len([1 for i in data_list if i['interview_stage'] >= 7]) + + if offer_num: + offer_chance = round(offer_num / count_num, 2) + else: + offer_chance = 0 + + if work_num: + work_chance = round(work_num / count_num, 2) + else: + work_chance = 0 + res_msg[key]['count'] = count_num + res_msg[key]['offer_num'] = offer_num + res_msg[key]['work_num'] = work_num + res_msg[key]['offer_chance'] = offer_chance + res_msg[key]['work_chance'] = work_chance + + return schemas.Msg(code=200, msg='ok', data=res_msg) diff --git a/crud/crud_jobs.py b/crud/crud_jobs.py index 3930ccd..43384bf 100644 --- a/crud/crud_jobs.py +++ b/crud/crud_jobs.py @@ -8,7 +8,12 @@ __all__ = 'jobs', class CRUDJobs(CRUDBase): # 获取所有对应职位字段的数据 async def all_field(self, db: AsyncIOMotorDatabase): - return await self.find_many(db, {}) + return await self.find_many(db, {}, {'_id': 0}) + + # 获取所有对应职位指定字段的数据 + async def all_some_field(self, db: AsyncIOMotorDatabase): + return await self.find_many(db, {}, {'_id': 0, 'job_id': 1, 'job_sector': 1, 'principal': 1, 'job_num': 1, + 'start_time': 1, 'now_job_num': 1, 'job_name': 1}) # 获取所有对应条件职位字段的数据 async def all_fields(self, db: AsyncIOMotorDatabase, data_in: schemas.Jobs): @@ -39,7 +44,7 @@ class CRUDJobs(CRUDBase): # 获取对应jobid的信息 async def find_job(self, db: AsyncIOMotorDatabase, job_id): - return await self.find_one(db, {'job_id':job_id}) + return await self.find_one(db, {'job_id': job_id}) jobs = CRUDJobs('jobs') diff --git a/models/interview_zsgc.py b/models/interview_zsgc.py index f61add1..6ff27fe 100644 --- a/models/interview_zsgc.py +++ b/models/interview_zsgc.py @@ -164,11 +164,11 @@ class InterviewDo: insert_data = self.data_in 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) values" + 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) values" now_time = datetime.datetime.now() for data in insert_data: s1 = data['event_time'] @@ -424,6 +424,94 @@ class InterviewDo: 'sql': sql } + # 渠道质量sql + def get_owner_form_sql(self): + findStr = '' + whereStr = '' + # 查询字段 + self.find_column = ["name", "owner_name", "interview_stage"] + for fstr in self.find_column: + findStr += fstr + ', ' + is_date = 0 + if self.where: + 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', '') + if whereStr: + sql = f"select {findStr} from HR.resumes where {whereStr}" + else: + sql = f"select {findStr} from HR.resumes where '1'" + if start_time: + sql += f" and toDate(event_time) >= `{start_time}`" + if end_time: + sql += f" and toDate(event_time) <= `{end_time}`" + # 没有日期条件 + else: + if whereStr: + sql = f"select {findStr} from HR.resumes where {whereStr}" + else: + sql = f"select {findStr} from HR.resumes" + print(sql) + return { + 'sql': sql + } + + # 渠道质量sql + def get_every_stage_form_sql(self, job_ids): + findStr = '' + whereStr = '' + # 查询字段 + self.find_column = ["name", "interview_stage", "job_id"] + for fstr in self.find_column: + findStr += fstr + ', ' + is_date = 0 + if self.where: + 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', '') + if whereStr: + sql = f"select {findStr} from HR.resumes where {whereStr} and job_id in {job_ids}" + else: + sql = f"select {findStr} from HR.resumes where job_id in {job_ids}" + if start_time: + sql += f" and toDate(event_time) >= `{start_time}`" + if end_time: + sql += f" and toDate(event_time) <= `{end_time}`" + # 没有日期条件 + else: + if whereStr: + sql = f"select {findStr} from HR.resumes where {whereStr} and job_id in {job_ids}" + else: + sql = f"select {findStr} from HR.resumes where job_id in {job_ids}" + print(sql) + return { + 'sql': sql + } + if __name__ == '__main__': find = re.search(r"\d+\.?\d*", "18岁") diff --git a/接口文档/候选人质量模板接口文档.txt b/接口文档/候选人质量模板接口文档.txt index 1f3334a..9ecc1ef 100644 --- a/接口文档/候选人质量模板接口文档.txt +++ b/接口文档/候选人质量模板接口文档.txt @@ -2,10 +2,9 @@ : { - "data_in": "string", - "interview_query": {"hr_name":""}, + "data_in": "", + "interview_query": {"hr_name":""}, # Ӧhr "find_column": [ - "string" ] } diff --git a/接口文档/渠道质量模板接口文档.txt b/接口文档/渠道质量模板接口文档.txt new file mode 100644 index 0000000..4a100db --- /dev/null +++ b/接口文档/渠道质量模板接口文档.txt @@ -0,0 +1,53 @@ +·: /api/v1/forms/get_owner_form + +: +{ + "data_in": "", # ɶΪ + "interview_query": {}, + "find_column": [ + ] +} + + +ֵ: +{ + "code": 200, + "msg": "ok", + "data": { + "ǰ": { + "count": 0, # + "offer_num": 0, # offer׶ # ͬ + "work_num": 0, # ְ׶ + "offer_chance": 0, # offer + "work_chance": 0 # ְ + }, + "˲ſ": { + "count": 2, + "offer_num": 2, + "work_num": 1, + "offer_chance": 1, + "work_chance": 0.5 + }, + "Ƹ": { + "count": 0, + "offer_num": 0, + "work_num": 0, + "offer_chance": 0, + "work_chance": 0 + }, + "BossֱƸ": { + "count": 0, + "offer_num": 0, + "work_num": 0, + "offer_chance": 0, + "work_chance": 0 + }, + "58ͬ": { + "count": 0, + "offer_num": 0, + "work_num": 0, + "offer_chance": 0, + "work_chance": 0 + } + } +} \ No newline at end of file diff --git a/接口文档/职位阶段模板接口文档.txt b/接口文档/职位阶段模板接口文档.txt new file mode 100644 index 0000000..7f5f9b2 --- /dev/null +++ b/接口文档/职位阶段模板接口文档.txt @@ -0,0 +1,46 @@ +·: /api/v1/forms/get_owner_form + +: +{ + "data_in": "", # ɶΪ + "interview_query": {}, + "find_column": [ + ] +} + + +ֵ: +{ + "code": 200, + "msg": "ok", + "data": { + "߼ϷԹʦ": { # ְλӦ + "job_name": "߼ϷԹʦ", # ְλ + "job_sector": "з", # + "principal": "a", # + "start_time": "2021-08-23T11:41:54.563000", # Ƹʼʱ + "job_num": 3, # Ƹ + "now_job_num": 14, # ְ + "ɸ": 0, + "ɸ": 0, + "": 0, + "offer": 0, + "ְ": 0, + "ְ": 14 + }, + "python": { + "job_name": "python", + "job_sector": "ƽ̨", + "principal": "", + "start_time": "2022-06-06T10:51:44.223000", + "job_num": 6, + "now_job_num": 0, + "ɸ": 0, + "ɸ": 0, + "": 0, + "offer": 0, + "ְ": 0, + "ְ": 0 + } + } +} \ No newline at end of file