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.
325 lines
11 KiB
325 lines
11 KiB
'use strict';
|
|
const moment = require('moment')
|
|
const fs = require('fs');
|
|
|
|
async function overtimeStatistic (ctx) {
|
|
try {
|
|
const { models } = ctx.fs.dc;
|
|
const { clickHouse } = ctx.app.fs
|
|
const { memberList, packageUserData, overtimeStatisticListDayType } = ctx.app.fs.utils
|
|
const {
|
|
keywordTarget, keyword, limit, page, orderBy, orderDirection,
|
|
startDate, endDate,
|
|
} = ctx.query
|
|
|
|
const userRes = await memberList({
|
|
keywordTarget, keyword, limit, page,
|
|
orderBy, orderDirection,
|
|
overtimeDayStatisticStartDate: startDate,
|
|
overtimeDayStatisticendDate: endDate,
|
|
overtimeCountStatistic: true,
|
|
overtimeCountStatisticStartDate: startDate,
|
|
overtimeCountStatisticendDate: endDate,
|
|
})
|
|
|
|
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
|
|
|
|
const sumRes = await overtimeStatisticListDayType({
|
|
startDate, endDate, pepUserIds
|
|
})
|
|
|
|
returnD.forEach(u => {
|
|
u.overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId)
|
|
})
|
|
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 exportOvertimeStatistic (ctx) {
|
|
try {
|
|
const { models } = ctx.fs.dc;
|
|
const { clickHouse } = ctx.app.fs
|
|
const { memberList, packageUserData, overtimeStatisticListDayType, simpleExcelDown, dayType, overtimeType } = ctx.app.fs.utils
|
|
const {
|
|
keywordTarget, keyword, limit, page, orderBy, orderDirection,
|
|
startDate, endDate,
|
|
} = ctx.query
|
|
|
|
const userRes = await memberList({
|
|
keywordTarget, keyword, limit, page,
|
|
orderBy, orderDirection,
|
|
overtimeDayStatisticStartDate: startDate,
|
|
overtimeDayStatisticendDate: endDate,
|
|
overtimeCountStatistic: true,
|
|
overtimeCountStatisticStartDate: startDate,
|
|
overtimeCountStatisticendDate: endDate,
|
|
})
|
|
|
|
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
|
|
|
|
const sumRes = await overtimeStatisticListDayType({
|
|
startDate, endDate, pepUserIds
|
|
})
|
|
|
|
returnD.forEach(d => {
|
|
d.departmrnt = d.departmrnt.map(dep => dep.name).join('、')
|
|
d.role = d.role.map(r => r.name).join('、')
|
|
let overtimeStatistic = sumRes.filter(s => s.pepUserId == d.pepUserId)
|
|
let totalDuration = 0
|
|
for (let dayTypeKey in dayType) {
|
|
for (let overtimeTypeKey in overtimeType) {
|
|
let corOverTimeSta = overtimeStatistic.find(o => o.compensate == overtimeTypeKey && o.dayType == dayTypeKey)
|
|
if (corOverTimeSta) {
|
|
d[overtimeTypeKey + dayTypeKey] = (corOverTimeSta.duration / 3600)
|
|
// .toFixed(1)
|
|
totalDuration += corOverTimeSta.duration / 3600
|
|
}
|
|
}
|
|
}
|
|
for (let overtimeTypeKey in overtimeType) {
|
|
d['sum' + overtimeTypeKey] = overtimeStatistic.reduce((sum, o) => {
|
|
if (o.compensate == overtimeTypeKey) {
|
|
sum += o.duration / 3600
|
|
totalDuration += o.duration / 3600
|
|
}
|
|
return sum
|
|
}, 0)
|
|
}
|
|
d.totalDuration = totalDuration
|
|
})
|
|
|
|
let overtimeTypeHeader = []
|
|
let sumOvertimeTypeHeader = []
|
|
for (let overtimeTypeKey in overtimeType) {
|
|
sumOvertimeTypeHeader.push({
|
|
title: `合计${overtimeType[overtimeTypeKey]}加班时长(小时)`,
|
|
key: 'sum' + overtimeTypeKey,
|
|
defaultValue: '0'
|
|
})
|
|
for (let dayTypeKey in dayType) {
|
|
overtimeTypeHeader.push({
|
|
title: dayType[dayTypeKey] + '-' + overtimeType[overtimeTypeKey],
|
|
key: overtimeTypeKey + dayTypeKey,
|
|
defaultValue: '0'
|
|
})
|
|
}
|
|
}
|
|
|
|
const header = [{
|
|
title: '员工编号',
|
|
key: 'userCode',
|
|
}, {
|
|
title: '姓名',
|
|
key: 'userName',
|
|
}, {
|
|
title: '所属部门',
|
|
key: 'departmrnt',
|
|
}, {
|
|
title: '职位',
|
|
key: 'role',
|
|
}, {
|
|
title: '加班次数(次)',
|
|
key: 'overtimeCount',
|
|
},]
|
|
.concat(overtimeTypeHeader)
|
|
.concat(sumOvertimeTypeHeader)
|
|
.concat([{
|
|
title: '合计加班时长(小时)',
|
|
key: 'totalDuration',
|
|
defaultValue: '0'
|
|
}])
|
|
|
|
const fileName = `加班统计_${startDate ? moment(startDate).format('YYYY-MM-DD') : ''}${startDate && endDate ? '-' : ''}${endDate ? moment(endDate).format('YYYY-MM-DD') : ''}${startDate || endDate ? '_' : ''}${moment().format('YYYYMMDDHHmmss')}` + '.csv'
|
|
const filePath = await simpleExcelDown({ data: returnD, 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 vacateType (ctx) {
|
|
try {
|
|
const { models } = ctx.fs.dc;
|
|
const { clickHouse } = ctx.app.fs
|
|
|
|
const vacateTypeRes = await clickHouse.hr.query(`
|
|
SELECT type FROM vacate GROUP BY type ORDER BY type DESC
|
|
`).toPromise()
|
|
|
|
ctx.status = 200;
|
|
ctx.body = vacateTypeRes
|
|
} catch (error) {
|
|
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
|
|
ctx.status = 400;
|
|
ctx.body = {
|
|
message: typeof error == 'string' ? error : undefined
|
|
}
|
|
}
|
|
}
|
|
|
|
async function vacateStatistic (ctx) {
|
|
try {
|
|
const { models } = ctx.fs.dc;
|
|
const { clickHouse } = ctx.app.fs
|
|
const { judgeHoliday, memberList, packageUserData, vacateStatisticListDayType } = ctx.app.fs.utils
|
|
const {
|
|
keywordTarget, keyword, limit, page, orderBy, orderDirection,
|
|
startDate, endDate,
|
|
} = ctx.query
|
|
|
|
const userRes = await memberList({
|
|
keywordTarget, keyword, limit, page,
|
|
orderBy, orderDirection,
|
|
vacateDayStatisticStartDate: startDate,
|
|
vacateDayStatisticendDate: endDate,
|
|
vacateDurationStatistic: true,
|
|
vacateCountStatistic: true,
|
|
vacateCountStatisticStartDate: startDate,
|
|
vacateCountStatisticendDate: endDate,
|
|
})
|
|
|
|
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
|
|
|
|
const sumRes = await vacateStatisticListDayType({
|
|
startDate, endDate, pepUserIds
|
|
})
|
|
|
|
returnD.forEach(u => {
|
|
u.vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId)
|
|
})
|
|
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 exportVacateStatistic (ctx) {
|
|
try {
|
|
const { models } = ctx.fs.dc;
|
|
const { clickHouse } = ctx.app.fs
|
|
const { memberList, packageUserData, vacateStatisticListDayType, overtimeStatisticListDayType, simpleExcelDown, dayType, overtimeType } = ctx.app.fs.utils
|
|
const {
|
|
keywordTarget, keyword, limit, page, orderBy, orderDirection,
|
|
startDate, endDate,
|
|
} = ctx.query
|
|
|
|
const vacateTypeRes = await clickHouse.hr.query(`
|
|
SELECT type FROM vacate GROUP BY type ORDER BY type DESC
|
|
`).toPromise()
|
|
|
|
const userRes = await memberList({
|
|
keywordTarget, keyword, limit, page,
|
|
orderBy, orderDirection,
|
|
vacateDayStatisticStartDate: startDate,
|
|
vacateDayStatisticendDate: endDate,
|
|
vacateDurationStatistic: true,
|
|
vacateCountStatistic: true,
|
|
vacateCountStatisticStartDate: startDate,
|
|
vacateCountStatisticendDate: endDate,
|
|
})
|
|
|
|
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
|
|
|
|
const sumRes = await vacateStatisticListDayType({
|
|
startDate, endDate, pepUserIds
|
|
})
|
|
|
|
returnD.forEach(u => {
|
|
u.departmrnt = u.departmrnt.map(dep => dep.name).join('、')
|
|
u.role = u.role.map(r => r.name).join('、')
|
|
|
|
let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId)
|
|
for (let { type } of vacateTypeRes) {
|
|
u[type] = vacateStatistic.reduce((sum, v) => {
|
|
if (v.type == type) {
|
|
sum += v.duration / 3600
|
|
}
|
|
return sum
|
|
}, 0)
|
|
}
|
|
u.vacateDayStatisticDuration = (u.vacateDayStatisticDuration || 0) / 3600
|
|
})
|
|
|
|
const header = [{
|
|
title: '员工编号',
|
|
key: 'userCode',
|
|
}, {
|
|
title: '姓名',
|
|
key: 'userName',
|
|
}, {
|
|
title: '所属部门',
|
|
key: 'departmrnt',
|
|
}, {
|
|
title: '职位',
|
|
key: 'role',
|
|
},]
|
|
.concat(vacateTypeRes.map(v => {
|
|
return {
|
|
title: `${v.type}请假时长(小时)`,
|
|
key: v.type,
|
|
defaultValue: '0',
|
|
}
|
|
}))
|
|
.concat(
|
|
[{
|
|
title: '合计请假次数(次)',
|
|
key: 'vacateCount',
|
|
defaultValue: '0',
|
|
}, {
|
|
title: '合计请假时长(小时)',
|
|
key: 'vacateDayStatisticDuration',
|
|
defaultValue: '0',
|
|
}]
|
|
)
|
|
|
|
const fileName = `请假统计_${startDate ? moment(startDate).format('YYYY-MM-DD') : ''}${startDate && endDate ? '-' : ''}${endDate ? moment(endDate).format('YYYY-MM-DD') : ''}${startDate || endDate ? '_' : ''}${moment().format('YYYYMMDDHHmmss')}` + '.csv'
|
|
const filePath = await simpleExcelDown({ data: returnD, 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
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
overtimeStatistic,
|
|
exportOvertimeStatistic,
|
|
vacateType,
|
|
vacateStatistic,
|
|
exportVacateStatistic,
|
|
};
|