diff --git a/api/app/lib/controllers/attendance/index.js b/api/app/lib/controllers/attendance/index.js index c60cc48..d3d56b5 100644 --- a/api/app/lib/controllers/attendance/index.js +++ b/api/app/lib/controllers/attendance/index.js @@ -1,4 +1,5 @@ 'use strict'; +const moment = require('moment') async function overtimeStatistic (ctx) { try { @@ -14,7 +15,10 @@ async function overtimeStatistic (ctx) { keywordTarget, keyword, limit, page, orderBy, orderDirection, overtimeDayStatisticStartDate: startDate, - overtimeDayStatisticendDate: endDate + overtimeDayStatisticendDate: endDate, + overtimeCountStatistic: true, + overtimeCountStatisticStartDate: startDate, + overtimeCountStatisticendDate: endDate, }) let returnD = [] @@ -62,30 +66,10 @@ async function overtimeStatistic (ctx) { }] : [], del: undefined, pepuserid: undefined, - "vacateStartTime": undefined, - "vacateEndTime": undefined, - "overtimeStartTime": undefined, - "overtimeEndTime": undefined, }) } }) - // 查加班总数 - const countRes = await clickHouse.hr.query(` - SELECT - overtime.pep_user_id AS pepUserId, - count(pep_process_story_id) AS count - FROM overtime - WHERE overtime.pep_user_id IN (${pepUserIds.join(',')}) - ${startDate ? ` - AND overtime.start_time >= '${moment(startDate).format('YYYY-MM-DD')}' - `: ''} - ${endDate ? ` - AND overtime.start_time <= '${moment(endDate).format('YYYY-MM-DD')}' - ` : ''} - GROUP BY overtime.pep_user_id - `).toPromise() - const sumRes = await clickHouse.hr.query(` SELECT overtime.pep_user_id AS pepUserId, @@ -109,8 +93,6 @@ async function overtimeStatistic (ctx) { `).toPromise() returnD.forEach(u => { - u.overtimeCount = (countRes.find(c => c.pepUserId == u.pepUserId) || {}).count || 0 - u.overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) }) ctx.status = 200; @@ -127,6 +109,113 @@ async function overtimeStatistic (ctx) { } } +async function vacateStatistic (ctx) { + try { + const { models } = ctx.fs.dc; + const { clickHouse } = ctx.app.fs + const { judgeHoliday, memberList } = 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 returnD = [] + let pepUserIds = [] + userRes.rows.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 { + let obj = {} + for (let k in u) { + let nextKey = k.replace('hrMember.', '') + .replace('member.', '') + if (nextKey.includes('_')) { + nextKey = nextKey.toLowerCase() + .replace( + /(_)[a-z]/g, + (L) => L.toUpperCase() + ) + .replace(/_/g, '') + } + obj[nextKey] = u[k] + } + pepUserIds.push(u.pepUserId) + returnD.push({ + ...obj, + departmrnt: u.depId ? [{ + id: u.depId, + name: u.depName + }] : [], + role: u.roleId ? [{ + id: u.roleId, + name: u.roleName + }] : [], + del: undefined, + pepuserid: undefined, + }) + } + }) + + const sumRes = await clickHouse.hr.query(` + SELECT + vacate.pep_user_id AS pepUserId, + vacate.type AS type, + sum(vacate_day.duration) AS duration + FROM vacate_day + INNER JOIN vacate + ON vacate.id = vacate_day.vacate_id + AND vacate.pep_user_id IN (${pepUserIds.join(',')}) + WHERE vacate.pep_user_id IN (${pepUserIds.join(',')}) + ${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.type, vacate.pep_user_id + `).toPromise() + + 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 + } + } +} + module.exports = { overtimeStatistic, + vacateStatistic, }; \ No newline at end of file diff --git a/api/app/lib/controllers/member/index.js b/api/app/lib/controllers/member/index.js index f40fd47..2d887d2 100644 --- a/api/app/lib/controllers/member/index.js +++ b/api/app/lib/controllers/member/index.js @@ -293,7 +293,7 @@ async function list (ctx) { const userRes = await memberList({ keywordTarget, keyword, limit, page, state, hiredateStart, hiredateEnd, marital, native, workPlace, - orderBy, orderDirection, + orderBy, orderDirection, nowAttendanceTime: true }) let returnD = [] @@ -537,7 +537,7 @@ async function exportData (ctx) { const { simpleExcelDown, memberList } = ctx.app.fs.utils const { keywordTarget, keyword, limit, page, state, keys = '' } = ctx.query - const userRes = await memberList({ keywordTarget, keyword, limit, page, state }) + const userRes = await memberList({ keywordTarget, keyword, limit, page, state, nowAttendanceTime: true }) const tableAttributes = models['Member'].tableAttributes const optionKeys = keys.split(',') diff --git a/api/app/lib/routes/attendance/index.js b/api/app/lib/routes/attendance/index.js index 24c4e6a..9448750 100644 --- a/api/app/lib/routes/attendance/index.js +++ b/api/app/lib/routes/attendance/index.js @@ -5,4 +5,7 @@ const attendance = require('../../controllers/attendance'); module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/attendance/overtime'] = { content: '加班统计', visible: true }; router.get('/attendance/overtime', attendance.overtimeStatistic); + + app.fs.api.logAttr['GET/attendance/vacate'] = { content: '请假统计', visible: true }; + router.get('/attendance/vacate', attendance.vacateStatistic); }; \ No newline at end of file diff --git a/api/app/lib/utils/member.js b/api/app/lib/utils/member.js index d68021d..40673be 100644 --- a/api/app/lib/utils/member.js +++ b/api/app/lib/utils/member.js @@ -8,7 +8,11 @@ module.exports = function (app, opts) { keywordTarget, keyword, limit, page, state, hiredateStart, hiredateEnd, marital, native, workPlace, orderBy, orderDirection, - overtimeDayStatisticStartDate, overtimeDayStatisticendDate + nowAttendanceTime, + overtimeDayStatisticStartDate, overtimeDayStatisticendDate, + overtimeCountStatistic, overtimeCountStatisticStartDate, overtimeCountStatisticendDate, + vacateDayStatisticStartDate, vacateDayStatisticendDate, + vacateDurationStatistic, vacateCountStatistic, vacateCountStatisticStartDate, vacateCountStatisticendDate }) { const { judgeHoliday } = app.fs.utils const { clickHouse } = app.fs @@ -62,10 +66,34 @@ module.exports = function (app, opts) { let overtimeDayStatisticWhere = [] if (overtimeDayStatisticStartDate) { - overtimeDayStatisticWhere.push(`overtime_day.day >= '${moment(startDate).format('YYYY-MM-DD')}'`) + overtimeDayStatisticWhere.push(`overtime_day.day >= '${moment(overtimeDayStatisticStartDate).format('YYYY-MM-DD')}'`) } if (overtimeDayStatisticendDate) { - overtimeDayStatisticWhere.push(`overtime_day.day <= '${moment(endDate).format('YYYY-MM-DD')}'`) + overtimeDayStatisticWhere.push(`overtime_day.day <= '${moment(overtimeDayStatisticendDate).format('YYYY-MM-DD')}'`) + } + + let overtimeCountStatisticWhere = [] + if (overtimeCountStatisticStartDate) { + overtimeCountStatisticWhere.push(`overtime.start_time >= '${moment(overtimeCountStatisticStartDate).format('YYYY-MM-DD')}'`) + } + if (overtimeCountStatisticendDate) { + overtimeCountStatisticWhere.push(`overtime.end_time <= '${moment(overtimeCountStatisticendDate).format('YYYY-MM-DD')}'`) + } + + let vacateDayStatisticWhere = [] + if (vacateDayStatisticStartDate) { + vacateDayStatisticWhere.push(`vacate_day.day >= '${moment(vacateDayStatisticStartDate).format('YYYY-MM-DD')}'`) + } + if (vacateDayStatisticendDate) { + vacateDayStatisticWhere.push(`vacate_day.day <= '${moment(vacateDayStatisticendDate).format('YYYY-MM-DD')}'`) + } + + let vacateCountStatisticWhere = [] + if (vacateCountStatisticStartDate) { + vacateCountStatisticWhere.push(`vacate.start_time >= '${moment(vacateCountStatisticStartDate).format('YYYY-MM-DD')}'`) + } + if (vacateCountStatisticendDate) { + vacateCountStatisticWhere.push(`vacate.end_time <= '${moment(vacateCountStatisticendDate).format('YYYY-MM-DD')}'`) } // CRAZY const innerSelectQuery = ` @@ -78,33 +106,39 @@ module.exports = function (app, opts) { ${keywordTarget == 'name' && keyword ? ` AND user.name LIKE '%${keyword}%' `: ''} - ${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN ( - SELECT - pep_user_id, - any(start_time) AS vacateStartTime, - any(end_time) AS vacateEndTime - FROM vacate - WHERE - start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' - AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' - GROUP BY pep_user_id - ) AS hrVacate - ON hrVacate.pep_user_id = member.pep_user_id - - LEFT JOIN ( - SELECT - pep_user_id, - any(start_time) AS overtimeStartTime, - any(end_time) AS overtimeEndTime - FROM overtime - WHERE - start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' - AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' - GROUP BY pep_user_id - ) AS hrOvertime - ON hrOvertime.pep_user_id = member.pep_user_id - - ${orderBy == 'overtimeTakeRestSum' || orderBy == 'overtimePaySum' || orderBy == 'overtimeSum' ? + + ${nowAttendanceTime ? ` + ${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN ( + SELECT + pep_user_id, + any(start_time) AS vacateStartTime, + any(end_time) AS vacateEndTime + FROM vacate + WHERE + start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + GROUP BY pep_user_id + ) AS hrVacate + ON hrVacate.pep_user_id = member.pep_user_id + `: ''} + ${nowAttendanceTime ? ` + LEFT JOIN ( + SELECT + pep_user_id, + any(start_time) AS overtimeStartTime, + any(end_time) AS overtimeEndTime + FROM overtime + WHERE + start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + GROUP BY pep_user_id + ) AS hrOvertime + ON hrOvertime.pep_user_id = member.pep_user_id + `: ''} + + ${orderBy == 'overtimeTakeRestSum' || + orderBy == 'overtimePaySum' || + orderBy == 'overtimeSum' ? `LEFT JOIN ( SELECT overtime.pep_user_id AS pepUserId, @@ -121,6 +155,49 @@ module.exports = function (app, opts) { ) AS overtimeDayStatistic ON overtimeDayStatistic.pepUserId = member.pep_user_id`: ''} + ${overtimeCountStatistic ? ` + LEFT JOIN ( + SELECT + overtime.pep_user_id AS pepUserId, + count(pep_process_story_id) AS count + FROM overtime + ${overtimeCountStatisticWhere.length ? ` + WHERE ${overtimeCountStatisticWhere.join(' AND ')} + `: ''} + GROUP BY overtime.pep_user_id + ) AS overtimeCountStatistic + ON overtimeCountStatistic.pepUserId = member.pep_user_id + `: ''} + + ${vacateDurationStatistic || + orderBy == 'vacateSum' ? + `LEFT JOIN ( + SELECT + vacate.pep_user_id AS pepUserId, + sum(vacate_day.duration) AS duration + FROM vacate_day + INNER JOIN vacate + ON vacate.id = vacate_day.vacate_id + ${vacateDayStatisticWhere.length ? ` + WHERE ${vacateDayStatisticWhere.join(' AND ')} + `: ''} + GROUP BY vacate.pep_user_id + ) AS vacateDayStatistic + ON vacateDayStatistic.pepUserId = member.pep_user_id`: ''} + + ${vacateCountStatistic ? ` + LEFT JOIN ( + SELECT + vacate.pep_user_id AS pepUserId, + count(pep_process_story_id) AS count + FROM vacate + ${vacateCountStatisticWhere.length ? ` + WHERE ${vacateCountStatisticWhere.join(' AND ')} + `: ''} + GROUP BY vacate.pep_user_id + ) AS vacateCountStatistic + ON vacateCountStatistic.pepUserId = member.pep_user_id + `: ''} WHERE member.del = 0 ${keywordTarget == 'role' && keyword ? ` @@ -143,7 +220,7 @@ module.exports = function (app, opts) { ` : ''} ${state == 'dimission' ? `AND member.dimission_date IS NOT null` : ''} ${state == 'onJob' ? `AND member.dimission_date IS null` : ''} - ${whereFromSelectOption.length ? `AND ${whereFromSelectOption.join('AND')}` : ''} + ${whereFromSelectOption.length && nowAttendanceTime ? `AND ${whereFromSelectOption.join('AND')}` : ''} ${hiredateStart ? ` AND member.hiredate >= '${moment(hiredateStart).format('YYYY-MM-DD')}' `: ''} @@ -173,23 +250,39 @@ module.exports = function (app, opts) { department.id AS depId FROM ( SELECT - member.*, - - ${orderBy == 'overtimeTakeRestSum' || orderBy == 'overtimePaySum' || orderBy == 'overtimeSum' ? ` + ${orderBy == 'overtimeTakeRestSum' + || orderBy == 'overtimePaySum' + || orderBy == 'overtimeSum' ? ` overtimeDayStatistic.duration AS overtimeDayStatisticDuration `: ''} - hrVacate.vacateStartTime AS vacateStartTime, - hrVacate.vacateEndTime AS vacateEndTime, - hrOvertime.overtimeStartTime AS overtimeStartTime, - hrOvertime.overtimeEndTime AS overtimeEndTime + ${overtimeCountStatistic ? ` + overtimeCountStatistic.count AS overtimeCount, + `: ''} + + ${orderBy == 'vacateSum' || vacateDurationStatistic ? ` + vacateDayStatistic.duration AS vacateDayStatisticDuration, + `: ''} + + ${vacateCountStatistic ? ` + vacateCountStatistic.count AS vacateCount, + `: ''} + + ${nowAttendanceTime ? ` + hrVacate.vacateStartTime AS vacateStartTime, + hrVacate.vacateEndTime AS vacateEndTime, + hrOvertime.overtimeStartTime AS overtimeStartTime, + hrOvertime.overtimeEndTime AS overtimeEndTime, + `: ''} + + member.* ${innerSelectQuery} ${limit ? `LIMIT ${limit}` : ''} ${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} ) AS hrMember LEFT JOIN ${pepEmis}.user AS user - ON hrMember."member.pep_user_id" = user.id + ON pepUserId = user.id LEFT JOIN ${pepEmis}.user_role AS user_role ON ${pepEmis}.user_role.user = user.id LEFT JOIN ${pepEmis}.role AS role @@ -199,11 +292,23 @@ module.exports = function (app, opts) { LEFT JOIN ${pepEmis}.department AS department ON department.id = department_user.department ${whereOption.length ? `WHERE ${whereOption.join(' AND ')}` : ''} - ORDER BY ${orderBy == 'code' ? 'user.people_code' - : orderBy == 'hiredate' ? 'hrMember."member.hiredate"' - : orderBy == 'age' ? 'hrMember."member.birthday"' - : orderBy == 'overtimeTakeRestSum' || orderBy == 'overtimePaySum' || orderBy == 'overtimeSum' ? 'hrMember."member.overtimeDayStatisticDuration"' - : 'user.people_code'} + ORDER BY ${orderBy == 'code' ? + 'user.people_code' + : orderBy == 'hiredate' + ? 'hrMember."member.hiredate"' + : orderBy == 'age' + ? 'hrMember."member.birthday"' + : orderBy == 'overtimeTakeRestSum' + || orderBy == 'overtimePaySum' + || orderBy == 'overtimeSum' ? + 'hrMember."member.overtimeDayStatisticDuration"' + : orderBy == 'overtimeCount' ? + 'hrMember.overtimeCount' + : orderBy == 'vacateSum' ? + 'hrMember.vacateDayStatisticDuration' + : orderBy == 'vacateCount' ? + 'hrMember.vacateCount' + : 'user.people_code'} ${orderDirection || 'ASC'} `).toPromise()