渠道质量,阶段数据
This commit is contained in:
parent
bd1523b5c4
commit
db6dcc91de
@ -2,6 +2,7 @@ import operator
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
from copy import deepcopy
|
||||||
from fastapi import APIRouter, Depends, Request, File, UploadFile
|
from fastapi import APIRouter, Depends, Request, File, UploadFile
|
||||||
from motor.motor_asyncio import AsyncIOMotorDatabase
|
from motor.motor_asyncio import AsyncIOMotorDatabase
|
||||||
|
|
||||||
@ -21,12 +22,12 @@ router = APIRouter()
|
|||||||
|
|
||||||
# 候选人质量报表
|
# 候选人质量报表
|
||||||
@router.post("/man_mass_form")
|
@router.post("/man_mass_form")
|
||||||
async def interview_find(
|
async def man_mass_form(
|
||||||
request: Request,
|
request: Request,
|
||||||
interview: InterviewDo = Depends(InterviewDo),
|
interview: InterviewDo = Depends(InterviewDo),
|
||||||
db: CKDrive = Depends(get_ck_db),
|
db: CKDrive = Depends(get_ck_db),
|
||||||
) -> schemas.Msg:
|
) -> schemas.Msg:
|
||||||
""" interview面试数据查询 """
|
""" 候选人质量报表 """
|
||||||
await interview.init()
|
await interview.init()
|
||||||
res = interview.get_man_mass_form_sql()
|
res = interview.get_man_mass_form_sql()
|
||||||
sql = res['sql']
|
sql = res['sql']
|
||||||
@ -171,7 +172,7 @@ async def interview_find(
|
|||||||
else:
|
else:
|
||||||
work_exp['20-40'].append(i_name)
|
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:
|
||||||
if i_job_name in account:
|
if i_job_name in account:
|
||||||
job_name[i_job_name].append(i_name)
|
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)
|
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)
|
||||||
|
@ -8,7 +8,12 @@ __all__ = 'jobs',
|
|||||||
class CRUDJobs(CRUDBase):
|
class CRUDJobs(CRUDBase):
|
||||||
# 获取所有对应职位字段的数据
|
# 获取所有对应职位字段的数据
|
||||||
async def all_field(self, db: AsyncIOMotorDatabase):
|
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):
|
async def all_fields(self, db: AsyncIOMotorDatabase, data_in: schemas.Jobs):
|
||||||
@ -39,7 +44,7 @@ class CRUDJobs(CRUDBase):
|
|||||||
# 获取对应jobid的信息
|
# 获取对应jobid的信息
|
||||||
async def find_job(self, db: AsyncIOMotorDatabase, job_id):
|
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')
|
jobs = CRUDJobs('jobs')
|
||||||
|
@ -424,6 +424,94 @@ class InterviewDo:
|
|||||||
'sql': sql
|
'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__':
|
if __name__ == '__main__':
|
||||||
find = re.search(r"\d+\.?\d*", "18岁")
|
find = re.search(r"\d+\.?\d*", "18岁")
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
参数:
|
参数:
|
||||||
{
|
{
|
||||||
"data_in": "string",
|
"data_in": "",
|
||||||
"interview_query": {"hr_name":"Îâ²Ù"},
|
"interview_query": {"hr_name":"吴操"}, # 对应hr的名字
|
||||||
"find_column": [
|
"find_column": [
|
||||||
"string"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
53
接口文档/渠道质量模板接口文档.txt
Normal file
53
接口文档/渠道质量模板接口文档.txt
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
接口文档/职位阶段模板接口文档.txt
Normal file
46
接口文档/职位阶段模板接口文档.txt
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user