人力资源
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

874 lines
28 KiB

'use strict';
const moment = require('moment')
const fs = require('fs');
async function add(ctx) {
try {
const { models } = ctx.fs.dc;
const {
pepUserId, idNumber, idPhoto, gender, birthday, nativePlace, marital,
politicsStatus, phoneNumber, workPlace, graduatedFrom, educationBackground, specialty, graduationDate, hiredate, turnProbationPeriod, regularDate, dimissionDate, experienceYear, occupationalHistory, vitae
} = ctx.request.body
const existMemberRes = await models.Member.findOne({
where: {
pepUserId
}
})
if (existMemberRes && !existMemberRes.del) {
throw '当前人员信息已存在'
}
let storageData = {
pepUserId, idNumber, idPhoto, gender, birthday, nativePlace, marital,
politicsStatus, phoneNumber, workPlace, graduatedFrom, educationBackground, specialty, graduationDate, hiredate, turnProbationPeriod, regularDate, dimissionDate, experienceYear, occupationalHistory, vitae,
del: false
}
if (existMemberRes && existMemberRes.del) {
await models.Member.update(storageData, {
where: {
pepUserId,
}
})
} else {
await models.Member.create(storageData)
}
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function edit(ctx) {
try {
const { models } = ctx.fs.dc;
const {
pepUserId, idNumber, idPhoto, gender, birthday, nativePlace, marital,
politicsStatus, phoneNumber, workPlace, graduatedFrom, educationBackground, specialty, graduationDate, hiredate, turnProbationPeriod, regularDate, dimissionDate, experienceYear, occupationalHistory, vitae
} = ctx.request.body
const existMemberRes = await models.Member.findOne({
where: {
pepUserId
}
})
if (!existMemberRes) {
throw '当前人员信息不存在'
}
let storageData = {
pepUserId, idNumber, idPhoto, gender, birthday, nativePlace, marital,
politicsStatus, phoneNumber, workPlace, graduatedFrom, educationBackground, specialty, graduationDate, hiredate, turnProbationPeriod, regularDate, dimissionDate, experienceYear, occupationalHistory, vitae,
del: false
}
await models.Member.update(storageData, {
where: {
pepUserId: pepUserId
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function searchPepMember(ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { keyword, code } = ctx.query
let whereOption = []
if (keyword) {
// whereOption.push(`user.id = ${keyword}`)
// whereOption.push(`user.name LIKE '${keyword}'`)
}
if (code) {
whereOption.push(`user.people_code = '${code}'`)
}
const userRes = await clickHouse.pepEmis.query(`
SELECT
user.id AS pepUserId,
user.people_code AS userCode,
basicdata_post.name AS userPost,
user.name AS userName,
role.name AS roleName,
role.id AS roleId,
department.name AS depName,
department.id AS depId
FROM
user
LEFT JOIN user_role
ON user_role.user = user.id
LEFT JOIN role
ON role.id = user_role.role
LEFT JOIN basicdata_post
ON basicdata_post.id = user.post
LEFT JOIN department_user
ON department_user.user = user.id
LEFT JOIN department
ON department.id = department_user.department
WHERE
user.delete = '0'
${whereOption.length ? `AND ${whereOption.join(' OR ')}` : ''}
`).toPromise()
let returnD = []
userRes.forEach(u => {
let existUser = returnD.find(r => r.pepUserId == u.pepUserId)
if (existUser) {
if (u.depId && !existUser.departmrnt.some(d => d.id == u.depId)) {
existUser.departmrnt.push({
id: u.depId,
name: u.depName
})
}
if (u.roleId && !existUser.role.some(r => r.id == u.roleId)) {
existUser.role.push({
id: u.roleId,
name: u.roleName
})
}
} else {
returnD.push({
pepUserId: u.pepUserId,
name: u.userName,
userCode: u.userCode,
userPost: u.userPost,
departmrnt: u.depId ? [{
id: u.depId,
name: u.depName
}] : [],
role: u.roleId ? [{
id: u.roleId,
name: u.roleName
}] : []
})
}
})
ctx.status = 200;
ctx.body = returnD
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function del(ctx) {
try {
const { models } = ctx.fs.dc;
const { pepUserId } = ctx.query
await models.Member.update({
del: true,
}, {
where: {
pepUserId,
}
})
await models.SalesDistribution.update({//顺便把销售人员删了
del: true,
}, {
where: {
pepUserId,
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function nativePlaceList(ctx) {
// 获取已有的户籍地列表
try {
const { models } = ctx.fs.dc;
const nRes = await models.Member.findAll({
attributes: ['nativePlace'],
group: 'nativePlace',
where: {
nativePlace: { $ne: null }
}
})
ctx.status = 200;
ctx.body = nRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function workPlaceList(ctx) {
// 获取已有的工作地列表
try {
const { models } = ctx.fs.dc;
const wRes = await models.Member.findAll({
attributes: ['workPlace'],
group: 'workPlace',
where: {
workPlace: { $ne: null }
}
})
ctx.status = 200;
ctx.body = wRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function maritalList(ctx) {
// 获取已有的婚育状况列表
try {
const { models } = ctx.fs.dc;
const mRes = await models.Member.findAll({
attributes: ['marital'],
group: 'marital',
where: {
marital: { $ne: null }
}
})
ctx.status = 200;
ctx.body = mRes
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function list(ctx) {
try {
const { models } = ctx.fs.dc;
const { judgeHoliday, memberList, packageUserData } = ctx.app.fs.utils
const {
keywordTarget, keyword, limit, page, state,
hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection,
} = ctx.query
const userRes = await memberList({
keywordTarget, keyword, limit, page, state,
hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection,
nowAttendanceTime: true
})
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes, {
state: true,
})
ctx.status = 200;
ctx.body = {
count: userRes.count,
rows: returnD
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function overTimeStatistics(ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { database: pepEmis } = clickHouse.pepEmis.opts.config
const { startDate, endDate, pepUserId } = ctx.query
const timeOption = []
if (startDate && endDate) {
timeOption.push(
`start_time <= '${moment(endDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'
AND start_time >= '${moment(startDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
)
}
const dataRes = await clickHouse.hr.query(`
SELECT
compensate,
create_at AS createTime,
start_time AS startTime,
end_time AS endTime,
pay_dayoff AS payDayoff,
pay_festivals AS payFestivals,
pay_workday AS payWorkday,
duration,
reason,
take_rest_dayoff AS takeRestDayoff,
take_rest_festivals AS takeRestFestivals,
take_rest_workday AS takeRestWorkday,
wpStory.id AS storyId
FROM
overtime
INNER JOIN ${pepEmis}.workflow_process_history AS wpStory
ON wpStory.id = overtime.pep_process_story_id
WHERE overtime.pep_user_id = ${pepUserId}
${timeOption.length ? `AND ${timeOption.join(' AND ')}` : ''}
`).toPromise()
const statisticRes = await clickHouse.hr.query(`
SELECT
count(overtime.id) AS overTimeCount,
sum(pay_dayoff) AS sumPayDayoff,
sum(pay_festivals) AS sumPayFestivals,
sum(pay_workday) AS sumPayWorkday,
sum(take_rest_dayoff) AS sumTakeRestDayoff,
sum(take_rest_festivals) AS sumTakeRestFestivals,
sum(take_rest_workday) AS sumTakeRestWorkday
FROM
overtime
INNER JOIN ${pepEmis}.workflow_process_history AS wpStory
ON wpStory.id = overtime.pep_process_story_id
${timeOption.length ? `AND ${timeOption.join(' AND ')}` : ''}
WHERE overtime.pep_user_id = ${pepUserId}
GROUP BY overtime.pep_user_id
`).toPromise()
const statisticDayRes = await clickHouse.hr.query(`
SELECT
overtime_day.day,
sum(overtime_day.duration) AS duration,
overtime.compensate AS compensate
FROM overtime_day
INNER JOIN overtime
ON overtime.id = overtime_day.overtime_id
AND overtime.pep_user_id = ${pepUserId}
${startDate ? `
AND overtime_day.day >= '${moment(startDate).format('YYYY-MM-DD')}'
`: ''}
${endDate ? `
AND overtime_day.day <= '${moment(endDate).format('YYYY-MM-DD')}'
` : ''}
GROUP BY overtime_day.day, overtime.compensate
`).toPromise()
let returnD = {
...(statisticRes.length ? statisticRes[0] : {}),
data: dataRes,
dayStatisticData: statisticDayRes.sort((a, b) => moment(a.day) - moment(b.day))
}
ctx.status = 200;
ctx.body = returnD
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function vacateStatistics(ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { database: pepEmis } = clickHouse.pepEmis.opts.config
const { startDate, endDate, pepUserId } = ctx.query
const timeOption = []
if (startDate) {
// 按发起时间
// timeOption.push(
// `wpStory.create_at >= '${moment(startDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
// )
// 按请假开始时间
timeOption.push(
`start_time >= '${moment(startDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
)
}
if (endDate) {
// timeOption.push(
// `wpStory.create_at <= '${moment(endDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
// )
timeOption.push(
`start_time <= '${moment(endDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
)
}
const dataRes = await clickHouse.hr.query(`
SELECT
type,
create_at AS createTime,
start_time AS startTime,
end_time AS endTime,
duration,
reason,
wpStory.id AS storyId
FROM
vacate
INNER JOIN ${pepEmis}.workflow_process_history AS wpStory
ON wpStory.id = vacate.pep_process_story_id
WHERE vacate.pep_user_id = ${pepUserId}
${timeOption.length ? `AND ${timeOption.join(' AND ')}` : ''}
`).toPromise()
const statisticRes = await clickHouse.hr.query(`
SELECT
type,
count(vacate.id) AS count,
sum(duration) AS sumDuration
FROM
vacate
INNER JOIN ${pepEmis}.workflow_process_history AS wpStory
ON wpStory.id = vacate.pep_process_story_id
${timeOption.length ? `AND ${timeOption.join(' AND ')}` : ''}
WHERE vacate.pep_user_id = ${pepUserId}
GROUP BY type
`).toPromise()
const statisticDayRes = await clickHouse.hr.query(`
SELECT vacate_day.day, sum(vacate_day.duration) AS duration
FROM vacate_day
INNER JOIN vacate
ON vacate.id = vacate_day.vacate_id
AND vacate.pep_user_id = ${pepUserId}
${startDate ? `
AND vacate_day.day >= '${moment(startDate).format('YYYY-MM-DD')}'
`: ''}
${endDate ? `
AND vacate_day.day <= '${moment(endDate).format('YYYY-MM-DD')}'
` : ''}
GROUP BY vacate_day.day
`).toPromise()
let returnD = {
statistic: statisticRes,
data: dataRes,
dayStatisticData: statisticDayRes.sort((a, b) => moment(a.day) - moment(b.day))
}
ctx.status = 200;
ctx.body = returnD
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function exportData(ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse, opts: { qiniu } } = ctx.app.fs
const { simpleExcelDown, memberList, packageUserData, UserAttribute } = ctx.app.fs.utils
const {
keywordTarget, keyword, limit, page, state, keys = '',
hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection,
} = ctx.query
const userRes = await memberList({
keywordTarget, keyword, limit, page, state,
hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection,
nowAttendanceTime: true
})
const tableAttributes = models['Member'].tableAttributes
const optionKeys = keys.split(',')
let { packageUser: exportD, pepUserIds } = await packageUserData(userRes)
let preHeader = [{
title: '员工编号',
key: 'userCode',
}, {
title: '姓名',
key: 'userName',
}, {
title: '所属部门',
key: 'departmrnt',
}, {
title: '职位',
key: 'userJob',
}, {
title: '岗位',
key: 'userPost',
}, {
title: '在职状态',
key: 'userActiveStatus',
}, {
title: '绩点',
key: 'point',
}, {
title: '归属机构',
key: 'userOrganization',
}, {
title: '技术职级等级',
key: 'technicalGrade',
}]
let header = [].concat(preHeader)
for (let k in tableAttributes) {
const comment = tableAttributes[k].comment
if (k != 'id' && k != 'pepUserId' && comment) {
if ([].includes(k)) {
// 截住不想导出的字段
continue
}
header.push({
title: comment || '-',
key: k,
// index: tableAttributes[k].index,
})
}
}
if (optionKeys.includes('overtimeStatistic')) {
header = header.concat([{
title: '累计加班次数',
key: 'overTimeCount',
}, {
title: '累计加班总时长 / h',
key: 'overTimeDuration',
},])
}
if (optionKeys.includes('vacateStatistic')) {
header = header.concat([{
title: '累计请假次数',
key: 'vacateCount',
}, {
title: '累计请假总时长 / h',
key: 'vacateDuration',
},])
}
// 查询累计加班次数及总时长
const statisticOvertimeRes = await clickHouse.hr.query(`
SELECT
pep_user_id AS pepUserId,
count(id) AS count,
sum(duration) AS duration
FROM
overtime
WHERE pep_user_id IN (${pepUserIds.join(',')})
GROUP BY pep_user_id
`).toPromise()
const statisticVacateRes = await clickHouse.hr.query(`
SELECT
pep_user_id AS pepUserId,
count(id) AS count,
sum(duration) AS duration
FROM
vacate
WHERE pep_user_id IN (${pepUserIds.join(',')})
GROUP BY pep_user_id
`).toPromise()
exportD.forEach(d => {
d.departmrnt = d.departmrnt.map(dep => dep.name).join('、')
d.role = d.role.map(r => r.name).join('、')
d.userJob = d.userJob ? UserAttribute.jobDataSource[d.userJob - 1] : '';
d.userActiveStatus = d.userActiveStatus ? UserAttribute.activeStatusDataSource[d.userActiveStatus - 1] : '';
d.userOrganization = d.userOrganization ? UserAttribute.organizationDataSource[d.userOrganization - 1] : '';
d.idPhoto ? d.idPhoto = qiniu.domain + '/' + d.idPhoto : ''
d.vitae ? d.vitae = qiniu.domain + '/' + d.vitae : ''
const corOverTime = statisticOvertimeRes.find(so => so.pepUserId == d.pepUserId)
d.overTimeCount = corOverTime ? corOverTime.count : 0
d.overTimeDuration = corOverTime ? (corOverTime.duration / 3600).toFixed(1) : 0
const corVacate = statisticVacateRes.find(so => so.pepUserId == d.pepUserId)
d.vacateCount = corVacate ? corVacate.count : 0
d.vacateDuration = corVacate ? (corVacate.duration / 3600).toFixed(1) : 0
})
const fileName = `人员信息_${moment().format('YYYYMMDDHHmmss')}` + '.csv'
const filePath = await simpleExcelDown({ data: exportD, header, fileName: fileName })
const fileData = fs.readFileSync(filePath);
ctx.status = 200;
ctx.set('Content-Type', 'application/x-xls');
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
ctx.body = fileData;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function addMembersBulk(ctx) {
let errorMsg = { message: '导入员工信息失败' };
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
let addMembers = [];
let editMembers = [];
let memberList = await models.Member.findAll({
attributes: ['pepUserId']
});
data.map(d => {
let exist = memberList.find(m => m.pepUserId == d.pepUserId);//项企的人员编号字段还没有
if (exist) {
editMembers.push(d);
} else {
addMembers.push(d);
}
})
//处理新增的
if (addMembers.length) {
await models.Member.bulkCreate(addMembers);
}
//处理编辑的
if (editMembers.length) {
for (let i in editMembers) {
let { pepUserId, name, idNumber, gender, birthday, nativePlace, marital,
politicsStatus, phoneNumber, workPlace, graduatedFrom, educationBackground, specialty, graduationDate,
hiredate, turnProbationPeriod, regularDate, dimissionDate, experienceYear, occupationalHistory, del } = editMembers[i];
let dataToUpdate = {
name,
idNumber,
gender,
birthday,
nativePlace,
marital,
politicsStatus,
phoneNumber,
workPlace,
graduatedFrom,
educationBackground,
specialty,
graduationDate,
hiredate,
turnProbationPeriod,
regularDate,
dimissionDate,
experienceYear,
occupationalHistory,
del
}
await models.Member.update(dataToUpdate, { where: { pepUserId: pepUserId } });
}
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errorMsg;
}
}
//岗位评级
async function getPositionRating(ctx) {
try {
const { models } = ctx.fs.dc;
const { limit, page } = ctx.query;
const findObj = {
order: [["ratingTime", "desc"]]
};
if (Number(limit) > 0 && Number(page) >= 0) {
findObj.limit = Number(limit);
findObj.offset = Number(page) * Number(limit);
}
const list = await models.PositionRating.findAndCountAll(findObj);
if (list.rows.length) {
const userIds = list.rows.map(u => u.pepUserId);
/**查询user信息 */
const { clickHouse } = ctx.app.fs
const { database: pepEmis } = clickHouse.pepEmis.opts.config
const userRes = await clickHouse.hr.query(`
SELECT
user.id as userId,
user.name AS userName,
user.people_code AS userCode,
basicDataPost.name AS userPost,
department.name AS depName,
department.id AS depId,
user.job AS userJob,
user.active_status AS userActiveStatus,
user.organization AS userOrganization
FROM ${pepEmis}.user AS user
LEFT JOIN ${pepEmis}.basicdata_post AS basicDataPost
ON ${pepEmis}.basicdata_post.id = user.post
LEFT JOIN ${pepEmis}.department_user AS department_user
ON department_user.user = user.id
LEFT JOIN ${pepEmis}.department AS department
ON department.id = department_user.department
where user.id in (${userIds.join(",")} )
`).toPromise();
const rslt = [];
list.rows.map(item => {
const userInfo = userRes && userRes.filter(u => item.pepUserId == u.userId);
item.dataValues.department = userInfo.map(u => { return { depName: u.depName, depId: u.depId } });
item.dataValues.userName = userInfo.length && userInfo[0].userName;
const { theoryPassed, totalRatingPassed, ratingTime, ...rest } = item.dataValues
rslt.push({
...rest,
theoryPassed: theoryPassed ? '是' : '否',
totalRatingPassed: totalRatingPassed ? '是' : '否',
ratingTime: moment(ratingTime).format('YYYY-MM-DD'),
department: userInfo.map(u => { return { depName: u.depName, depId: u.depId } }),
userName: userInfo.length && userInfo[0].userName,
userPost: userInfo.length && userInfo[0].userPost
});
})
ctx.body = {
rows: rslt,
count: list.count
}
} else {
ctx.body = list;
}
ctx.status = 200;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
//新增岗位评级
async function postPositionRating(ctx) {
let errorMsg = { message: '导入岗位绩效失败' };
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
//处理新增的
if (data) {
const dataToUpdate = [];
if (data.length) {
data.map((item) => {
const { pepUserId, technicalGrade } = item;
dataToUpdate.push({ pepUserId, technicalGrade });
})
await models.PositionRating.bulkCreate(data, { transaction });
}
else {
await models.PositionRating.create(data, { transaction });
dataToUpdate.push({ pepUserId: data.pepUserId, technicalGtechnicalGrade: data.technicalGraderade });
}
for (let item in dataToUpdate) {
await models.Member.update({ technicalGrade: dataToUpdate[item].technicalGrade },
{ where: { pepUserId: dataToUpdate[item].pepUserId }, transaction });
}
}
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = errorMsg;
}
}
async function delPositionRating(ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
const { id } = ctx.params;
const oldData = await models.PositionRating.findOne({ where: { id: id } });
if (oldData) {
const positionRating = await models.PositionRating.findAll({
where: {
pepUserId: oldData.pepUserId,
id: { $not: oldData.id }
},
attributes: ["technicalGrade"],
order: [["ratingTime", "desc"]]
});
//更新员工信息中的技术等级
const technicalGrade = positionRating.length ? positionRating[0].technicalGrade : undefined;
await models.Member.update({ technicalGrade: technicalGrade },
{
where: { pepUserId: oldData.pepUserId, del: false },
transaction
});
await models.PositionRating.destroy({ where: { id: id }, transaction });
}
transaction.commit();
ctx.status = 204;
} catch (error) {
transaction.rollback();
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
add,
edit,
del,
searchPepMember,
list,
overTimeStatistics,
vacateStatistics,
exportData,
addMembersBulk,
nativePlaceList,
workPlaceList,
maritalList,
getPositionRating,
postPositionRating,
delPositionRating
}