3 changed files with 406 additions and 351 deletions
			
			
		| @ -1,371 +1,403 @@ | |||
| 'use strict'; | |||
| const moment = require('moment') | |||
| const fs = require('fs'); | |||
| const { getDataRange } = require('../auth/index') | |||
| 
 | |||
| 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 => { | |||
|          let overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | |||
|          u.overtimeDuration = overtimeStatistic.reduce((sum, os) => sum + os.duration, 0) | |||
|          u.overtimeStatistic = overtimeStatistic | |||
|       }) | |||
|       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 | |||
|       } | |||
|    } | |||
|     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 | |||
| 
 | |||
|         let dataRange = await getDataRange(ctx); | |||
|         if (dataRange.userIds && dataRange.userIds.length === 0) { | |||
|             ctx.status = 200; | |||
|             ctx.body = { | |||
|                 count: 0, | |||
|                 rows: [] | |||
|             } | |||
|         } else { | |||
|             const userRes = await memberList({ | |||
|                 keywordTarget, keyword, limit, page, | |||
|                 orderBy, orderDirection, | |||
|                 overtimeDayStatisticStartDate: startDate, | |||
|                 overtimeDayStatisticendDate: endDate, | |||
|                 overtimeCountStatistic: true, | |||
|                 overtimeCountStatisticStartDate: startDate, | |||
|                 overtimeCountStatisticendDate: endDate, | |||
|                 userIds: dataRange.userIds | |||
|             }) | |||
| 
 | |||
|             let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) | |||
| 
 | |||
|             const sumRes = await overtimeStatisticListDayType({ | |||
|                 startDate, endDate, pepUserIds | |||
|             }) | |||
| 
 | |||
|             returnD.forEach(u => { | |||
|                 let overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | |||
|                 u.overtimeDuration = overtimeStatistic.reduce((sum, os) => sum + os.duration, 0) | |||
|                 u.overtimeStatistic = overtimeStatistic | |||
|             }) | |||
|             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' | |||
|     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 | |||
|         let returnD = null; | |||
|         let dataRange = await getDataRange(ctx); | |||
|         if (dataRange.userIds && dataRange.userIds.length === 0) { | |||
|             returnD = []; | |||
|         } else { | |||
|             const userRes = await memberList({ | |||
|                 keywordTarget, keyword, limit, page, | |||
|                 orderBy, orderDirection, | |||
|                 overtimeDayStatisticStartDate: startDate, | |||
|                 overtimeDayStatisticendDate: endDate, | |||
|                 overtimeCountStatistic: true, | |||
|                 overtimeCountStatisticStartDate: startDate, | |||
|                 overtimeCountStatisticendDate: endDate, | |||
|                 userIds: dataRange.userIds | |||
|             }) | |||
| 
 | |||
|             let { packageUser, pepUserIds } = await packageUserData(userRes) | |||
|             returnD = packageUser; | |||
|             const sumRes = await overtimeStatisticListDayType({ | |||
|                 startDate, endDate, pepUserIds | |||
|             }) | |||
|          } | |||
|       } | |||
| 
 | |||
|       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 | |||
|       } | |||
|    } | |||
| 
 | |||
|             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((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 | |||
|     try { | |||
|         const { models } = ctx.fs.dc; | |||
|         const { clickHouse } = ctx.app.fs | |||
| 
 | |||
|       const vacateTypeRes = await clickHouse.hr.query(` | |||
|         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 | |||
|       } | |||
|    } | |||
|         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 | |||
|       }) | |||
| 
 | |||
|       const remarkList = await models.VacateRemark.findAll({}); //查询备注
 | |||
| 
 | |||
|       returnD.forEach(u => { | |||
|          let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | |||
|          let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | |||
|          u.vacateDuration = vacateStatistic.reduce((sum, vs) => sum + vs.duration, 0) | |||
|          u.vacateStatistic = vacateStatistic | |||
|          u.remark = remarkData.length ? remarkData[0].remark : null | |||
|       }) | |||
|       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 | |||
|       } | |||
|    } | |||
|     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 | |||
| 
 | |||
|         let dataRange = await getDataRange(ctx); | |||
|         if (dataRange.userIds && dataRange.userIds.length === 0) { | |||
|             ctx.status = 200; | |||
|             ctx.body = { | |||
|                 count: 0, | |||
|                 rows: [] | |||
|             } | |||
|         } else { | |||
|             const userRes = await memberList({ | |||
|                 keywordTarget, keyword, limit, page, | |||
|                 orderBy, orderDirection, | |||
|                 vacateDayStatisticStartDate: startDate, | |||
|                 vacateDayStatisticendDate: endDate, | |||
|                 vacateDurationStatistic: true, | |||
|                 vacateCountStatistic: true, | |||
|                 vacateCountStatisticStartDate: startDate, | |||
|                 vacateCountStatisticendDate: endDate, | |||
|                 userIds: dataRange.userIds | |||
|             }) | |||
| 
 | |||
|             let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) | |||
| 
 | |||
|             const sumRes = await vacateStatisticListDayType({ | |||
|                 startDate, endDate, pepUserIds | |||
|             }) | |||
| 
 | |||
|             const remarkList = await models.VacateRemark.findAll({}); //查询备注
 | |||
| 
 | |||
|             returnD.forEach(u => { | |||
|                 let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | |||
|                 let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | |||
|                 u.vacateDuration = vacateStatistic.reduce((sum, vs) => sum + vs.duration, 0) | |||
|                 u.vacateStatistic = vacateStatistic | |||
|                 u.remark = remarkData.length ? remarkData[0].remark : null | |||
|             }) | |||
|             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(` | |||
|     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()
 | |||
|         let returnD = null; | |||
|         let dataRange = await getDataRange(ctx); | |||
|         if (dataRange.userIds && dataRange.userIds.length === 0) { | |||
|             returnD = []; | |||
|         } else { | |||
|             const userRes = await memberList({ | |||
|                 keywordTarget, keyword, limit, page, | |||
|                 orderBy, orderDirection, | |||
|                 vacateDayStatisticStartDate: startDate, | |||
|                 vacateDayStatisticendDate: endDate, | |||
|                 vacateDurationStatistic: true, | |||
|                 vacateCountStatistic: true, | |||
|                 vacateCountStatisticStartDate: startDate, | |||
|                 vacateCountStatisticendDate: endDate, | |||
|                 userIds: dataRange.userIds | |||
|             }) | |||
| 
 | |||
|       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 | |||
|       }) | |||
| 
 | |||
|       const remarkList = await models.VacateRemark.findAll({}); //查询备注
 | |||
| 
 | |||
|       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 | |||
|          u.userActiveStatus = u.userActiveStatus == 1 ? '在职' : u.userActiveStatus == 2 ? '离职' : '特殊状态-特殊账号' | |||
|          let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | |||
|          u.remark = remarkData.length ? (remarkData[0].remark == '' ? '无' : remarkData[0].remark) : '无' | |||
|       }) | |||
| 
 | |||
|       const header = [{ | |||
|          title: '员工编号', | |||
|          key: 'userCode', | |||
|       }, { | |||
|          title: '姓名', | |||
|          key: 'userName', | |||
|       }, { | |||
|          title: '所属部门', | |||
|          key: 'departmrnt', | |||
|       }, { | |||
|          title: '职位', | |||
|          key: 'role', | |||
|       }, { | |||
|          title: '在职状态', | |||
|          key: 'userActiveStatus', | |||
|       },] | |||
|          .concat(vacateTypeRes.map(v => { | |||
|             return { | |||
|                title: `${v.type}请假时长(小时)`, | |||
|                key: v.type, | |||
|                defaultValue: '0', | |||
|             } | |||
|          })) | |||
|          .concat( | |||
|             [{ | |||
|                title: '合计请假次数(次)', | |||
|                key: 'vacateCount', | |||
|                defaultValue: '0', | |||
|             }, { | |||
|                title: '合计请假时长(小时)', | |||
|                key: 'vacateDayStatisticDuration', | |||
|                defaultValue: '0', | |||
|             }] | |||
|          ) | |||
|          .concat( | |||
|             [{ | |||
|                title: '备注', | |||
|                key: 'remark', | |||
|             }] | |||
|          ) | |||
| 
 | |||
|       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 | |||
|       } | |||
|    } | |||
|             let { packageUser, pepUserIds } = await packageUserData(userRes) | |||
|             returnD = packageUser; | |||
|             const sumRes = await vacateStatisticListDayType({ | |||
|                 startDate, endDate, pepUserIds | |||
|             }) | |||
| 
 | |||
|             const remarkList = await models.VacateRemark.findAll({}); //查询备注
 | |||
| 
 | |||
|             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 | |||
|                 u.userActiveStatus = u.userActiveStatus == 1 ? '在职' : u.userActiveStatus == 2 ? '离职' : '特殊状态-特殊账号' | |||
|                 let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | |||
|                 u.remark = remarkData.length ? (remarkData[0].remark == '' ? '无' : remarkData[0].remark) : '无' | |||
|             }) | |||
|         } | |||
|         const header = [{ | |||
|             title: '员工编号', | |||
|             key: 'userCode', | |||
|         }, { | |||
|             title: '姓名', | |||
|             key: 'userName', | |||
|         }, { | |||
|             title: '所属部门', | |||
|             key: 'departmrnt', | |||
|         }, { | |||
|             title: '职位', | |||
|             key: 'role', | |||
|         }, { | |||
|             title: '在职状态', | |||
|             key: 'userActiveStatus', | |||
|         },] | |||
|             .concat(vacateTypeRes.map(v => { | |||
|                 return { | |||
|                     title: `${v.type}请假时长(小时)`, | |||
|                     key: v.type, | |||
|                     defaultValue: '0', | |||
|                 } | |||
|             })) | |||
|             .concat( | |||
|                 [{ | |||
|                     title: '合计请假次数(次)', | |||
|                     key: 'vacateCount', | |||
|                     defaultValue: '0', | |||
|                 }, { | |||
|                     title: '合计请假时长(小时)', | |||
|                     key: 'vacateDayStatisticDuration', | |||
|                     defaultValue: '0', | |||
|                 }] | |||
|             ) | |||
|             .concat( | |||
|                 [{ | |||
|                     title: '备注', | |||
|                     key: 'remark', | |||
|                 }] | |||
|             ) | |||
| 
 | |||
|         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 vacateRemark(ctx) { | |||
|    try { | |||
|       const { models } = ctx.fs.dc; | |||
|       const { remark, pepUserId } = ctx.query; | |||
|       let oldData = await models.VacateRemark.findOne({ where: { pepUserId: pepUserId } }); | |||
|       if (oldData) { | |||
|          await models.VacateRemark.update({ remark, pepUserId }, { where: { pepUserId: pepUserId } }); | |||
|       } else { | |||
|          await models.VacateRemark.create({ remark, pepUserId }); | |||
|       } | |||
| 
 | |||
|       ctx.status = 200; | |||
|       ctx.body = '添加备注成功'; | |||
|    } catch (error) { | |||
|       ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); | |||
|       ctx.status = 400; | |||
|       ctx.body = { | |||
|          "message": "添加备注失败" | |||
|       } | |||
|    } | |||
|     try { | |||
|         const { models } = ctx.fs.dc; | |||
|         const { remark, pepUserId } = ctx.query; | |||
|         let oldData = await models.VacateRemark.findOne({ where: { pepUserId: pepUserId } }); | |||
|         if (oldData) { | |||
|             await models.VacateRemark.update({ remark, pepUserId }, { where: { pepUserId: pepUserId } }); | |||
|         } else { | |||
|             await models.VacateRemark.create({ remark, pepUserId }); | |||
|         } | |||
| 
 | |||
|         ctx.status = 200; | |||
|         ctx.body = '添加备注成功'; | |||
|     } catch (error) { | |||
|         ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); | |||
|         ctx.status = 400; | |||
|         ctx.body = { | |||
|             "message": "添加备注失败" | |||
|         } | |||
|     } | |||
| } | |||
| 
 | |||
| module.exports = { | |||
|    overtimeStatistic, | |||
|    exportOvertimeStatistic, | |||
|    vacateType, | |||
|    vacateStatistic, | |||
|    exportVacateStatistic, | |||
|    vacateRemark | |||
|     overtimeStatistic, | |||
|     exportOvertimeStatistic, | |||
|     vacateType, | |||
|     vacateStatistic, | |||
|     exportVacateStatistic, | |||
|     vacateRemark | |||
| }; | |||
					Loading…
					
					
				
		Reference in new issue