3 changed files with 406 additions and 351 deletions
			
			
		| @ -1,371 +1,403 @@ | |||||
| 'use strict'; | 'use strict'; | ||||
| const moment = require('moment') | const moment = require('moment') | ||||
| const fs = require('fs'); | const fs = require('fs'); | ||||
|  | const { getDataRange } = require('../auth/index') | ||||
| 
 | 
 | ||||
| async function overtimeStatistic(ctx) { | async function overtimeStatistic(ctx) { | ||||
|    try { |     try { | ||||
|       const { models } = ctx.fs.dc; |         const { models } = ctx.fs.dc; | ||||
|       const { clickHouse } = ctx.app.fs |         const { clickHouse } = ctx.app.fs | ||||
|       const { memberList, packageUserData, overtimeStatisticListDayType } = ctx.app.fs.utils |         const { memberList, packageUserData, overtimeStatisticListDayType } = ctx.app.fs.utils | ||||
|       const { |         const { | ||||
|          keywordTarget, keyword, limit, page, orderBy, orderDirection, |             keywordTarget, keyword, limit, page, orderBy, orderDirection, | ||||
|          startDate, endDate, |             startDate, endDate, | ||||
|       } = ctx.query |         } = ctx.query | ||||
| 
 | 
 | ||||
|       const userRes = await memberList({ |         let dataRange = await getDataRange(ctx); | ||||
|          keywordTarget, keyword, limit, page, |         if (dataRange.userIds && dataRange.userIds.length === 0) { | ||||
|          orderBy, orderDirection, |             ctx.status = 200; | ||||
|          overtimeDayStatisticStartDate: startDate, |             ctx.body = { | ||||
|          overtimeDayStatisticendDate: endDate, |                 count: 0, | ||||
|          overtimeCountStatistic: true, |                 rows: [] | ||||
|          overtimeCountStatisticStartDate: startDate, |             } | ||||
|          overtimeCountStatisticendDate: endDate, |         } else { | ||||
|       }) |             const userRes = await memberList({ | ||||
| 
 |                 keywordTarget, keyword, limit, page, | ||||
|       let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) |                 orderBy, orderDirection, | ||||
| 
 |                 overtimeDayStatisticStartDate: startDate, | ||||
|       const sumRes = await overtimeStatisticListDayType({ |                 overtimeDayStatisticendDate: endDate, | ||||
|          startDate, endDate, pepUserIds |                 overtimeCountStatistic: true, | ||||
|       }) |                 overtimeCountStatisticStartDate: startDate, | ||||
| 
 |                 overtimeCountStatisticendDate: endDate, | ||||
|       returnD.forEach(u => { |                 userIds: dataRange.userIds | ||||
|          let overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) |             }) | ||||
|          u.overtimeDuration = overtimeStatistic.reduce((sum, os) => sum + os.duration, 0) | 
 | ||||
|          u.overtimeStatistic = overtimeStatistic |             let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) | ||||
|       }) | 
 | ||||
|       ctx.status = 200; |             const sumRes = await overtimeStatisticListDayType({ | ||||
|       ctx.body = { |                 startDate, endDate, pepUserIds | ||||
|          count: userRes.count, |             }) | ||||
|          rows: returnD | 
 | ||||
|       } |             returnD.forEach(u => { | ||||
|    } catch (error) { |                 let overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | ||||
|       ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |                 u.overtimeDuration = overtimeStatistic.reduce((sum, os) => sum + os.duration, 0) | ||||
|       ctx.status = 400; |                 u.overtimeStatistic = overtimeStatistic | ||||
|       ctx.body = { |             }) | ||||
|          message: typeof error == 'string' ? error : undefined |             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) { | async function exportOvertimeStatistic(ctx) { | ||||
|    try { |     try { | ||||
|       const { models } = ctx.fs.dc; |         const { models } = ctx.fs.dc; | ||||
|       const { clickHouse } = ctx.app.fs |         const { clickHouse } = ctx.app.fs | ||||
|       const { memberList, packageUserData, overtimeStatisticListDayType, simpleExcelDown, dayType, overtimeType } = ctx.app.fs.utils |         const { memberList, packageUserData, overtimeStatisticListDayType, simpleExcelDown, dayType, overtimeType } = ctx.app.fs.utils | ||||
|       const { |         const { | ||||
|          keywordTarget, keyword, limit, page, orderBy, orderDirection, |             keywordTarget, keyword, limit, page, orderBy, orderDirection, | ||||
|          startDate, endDate, |             startDate, endDate, | ||||
|       } = ctx.query |         } = ctx.query | ||||
| 
 |         let returnD = null; | ||||
|       const userRes = await memberList({ |         let dataRange = await getDataRange(ctx); | ||||
|          keywordTarget, keyword, limit, page, |         if (dataRange.userIds && dataRange.userIds.length === 0) { | ||||
|          orderBy, orderDirection, |             returnD = []; | ||||
|          overtimeDayStatisticStartDate: startDate, |         } else { | ||||
|          overtimeDayStatisticendDate: endDate, |             const userRes = await memberList({ | ||||
|          overtimeCountStatistic: true, |                 keywordTarget, keyword, limit, page, | ||||
|          overtimeCountStatisticStartDate: startDate, |                 orderBy, orderDirection, | ||||
|          overtimeCountStatisticendDate: endDate, |                 overtimeDayStatisticStartDate: startDate, | ||||
|       }) |                 overtimeDayStatisticendDate: endDate, | ||||
| 
 |                 overtimeCountStatistic: true, | ||||
|       let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) |                 overtimeCountStatisticStartDate: startDate, | ||||
| 
 |                 overtimeCountStatisticendDate: endDate, | ||||
|       const sumRes = await overtimeStatisticListDayType({ |                 userIds: dataRange.userIds | ||||
|          startDate, endDate, pepUserIds |             }) | ||||
|       }) | 
 | ||||
| 
 |             let { packageUser, pepUserIds } = await packageUserData(userRes) | ||||
|       returnD.forEach(d => { |             returnD = packageUser; | ||||
|          d.departmrnt = d.departmrnt.map(dep => dep.name).join('、') |             const sumRes = await overtimeStatisticListDayType({ | ||||
|          d.role = d.role.map(r => r.name).join('、') |                 startDate, endDate, pepUserIds | ||||
|          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' |  | ||||
|             }) |             }) | ||||
|          } | 
 | ||||
|       } |             returnD.forEach(d => { | ||||
| 
 |                 d.departmrnt = d.departmrnt.map(dep => dep.name).join('、') | ||||
|       const header = [{ |                 d.role = d.role.map(r => r.name).join('、') | ||||
|          title: '员工编号', |                 let overtimeStatistic = sumRes.filter(s => s.pepUserId == d.pepUserId) | ||||
|          key: 'userCode', |                 let totalDuration = 0 | ||||
|       }, { |                 for (let dayTypeKey in dayType) { | ||||
|          title: '姓名', |                     for (let overtimeTypeKey in overtimeType) { | ||||
|          key: 'userName', |                         let corOverTimeSta = overtimeStatistic.find(o => o.compensate == overtimeTypeKey && o.dayType == dayTypeKey) | ||||
|       }, { |                         if (corOverTimeSta) { | ||||
|          title: '所属部门', |                             d[overtimeTypeKey + dayTypeKey] = (corOverTimeSta.duration / 3600) | ||||
|          key: 'departmrnt', |                             // .toFixed(1)
 | ||||
|       }, { |                             totalDuration += corOverTimeSta.duration / 3600 | ||||
|          title: '职位', |                         } | ||||
|          key: 'role', |                     } | ||||
|       }, { |                 } | ||||
|          title: '加班次数(次)', |                 for (let overtimeTypeKey in overtimeType) { | ||||
|          key: 'overtimeCount', |                     d['sum' + overtimeTypeKey] = overtimeStatistic((sum, o) => { | ||||
|       },] |                         if (o.compensate == overtimeTypeKey) { | ||||
|          .concat(overtimeTypeHeader) |                             sum += o.duration / 3600 | ||||
|          .concat(sumOvertimeTypeHeader) |                             // totalDuration += o.duration / 3600
 | ||||
|          .concat([{ |                         } | ||||
|             title: '合计加班时长(小时)', |                         return sum | ||||
|             key: 'totalDuration', |                     }, 0) | ||||
|             defaultValue: '0' |                 } | ||||
|          }]) |                 d.totalDuration = totalDuration | ||||
| 
 |             }) | ||||
|       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 }) |         let overtimeTypeHeader = [] | ||||
|       const fileData = fs.readFileSync(filePath); |         let sumOvertimeTypeHeader = [] | ||||
| 
 |         for (let overtimeTypeKey in overtimeType) { | ||||
|       ctx.status = 200; |             sumOvertimeTypeHeader.push({ | ||||
|       ctx.set('Content-Type', 'application/x-xls'); |                 title: `合计${overtimeType[overtimeTypeKey]}加班时长(小时)`, | ||||
|       ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName)); |                 key: 'sum' + overtimeTypeKey, | ||||
|       ctx.body = fileData; |                 defaultValue: '0' | ||||
|    } catch (error) { |             }) | ||||
|       ctx.fs.logger.error(`path: ${ctx.path}, error: error`); |             for (let dayTypeKey in dayType) { | ||||
|       ctx.status = 400; |                 overtimeTypeHeader.push({ | ||||
|       ctx.body = { |                     title: dayType[dayTypeKey] + '-' + overtimeType[overtimeTypeKey], | ||||
|          message: typeof error == 'string' ? error : undefined |                     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) { | async function vacateType(ctx) { | ||||
|    try { |     try { | ||||
|       const { models } = ctx.fs.dc; |         const { models } = ctx.fs.dc; | ||||
|       const { clickHouse } = ctx.app.fs |         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 |          SELECT type FROM vacate GROUP BY type ORDER BY type DESC | ||||
|       `).toPromise()
 |       `).toPromise()
 | ||||
| 
 | 
 | ||||
|       ctx.status = 200; |         ctx.status = 200; | ||||
|       ctx.body = vacateTypeRes |         ctx.body = vacateTypeRes | ||||
|    } catch (error) { |     } catch (error) { | ||||
|       ctx.fs.logger.error(`path: ${ctx.path}, error: error`); |         ctx.fs.logger.error(`path: ${ctx.path}, error: error`); | ||||
|       ctx.status = 400; |         ctx.status = 400; | ||||
|       ctx.body = { |         ctx.body = { | ||||
|          message: typeof error == 'string' ? error : undefined |             message: typeof error == 'string' ? error : undefined | ||||
|       } |         } | ||||
|    } |     } | ||||
| } | } | ||||
| 
 | 
 | ||||
| async function vacateStatistic(ctx) { | async function vacateStatistic(ctx) { | ||||
|    try { |     try { | ||||
|       const { models } = ctx.fs.dc; |         const { models } = ctx.fs.dc; | ||||
|       const { clickHouse } = ctx.app.fs |         const { clickHouse } = ctx.app.fs | ||||
|       const { judgeHoliday, memberList, packageUserData, vacateStatisticListDayType } = ctx.app.fs.utils |         const { judgeHoliday, memberList, packageUserData, vacateStatisticListDayType } = ctx.app.fs.utils | ||||
|       const { |         const { | ||||
|          keywordTarget, keyword, limit, page, orderBy, orderDirection, |             keywordTarget, keyword, limit, page, orderBy, orderDirection, | ||||
|          startDate, endDate, |             startDate, endDate, | ||||
|       } = ctx.query |         } = ctx.query | ||||
| 
 | 
 | ||||
|       const userRes = await memberList({ |         let dataRange = await getDataRange(ctx); | ||||
|          keywordTarget, keyword, limit, page, |         if (dataRange.userIds && dataRange.userIds.length === 0) { | ||||
|          orderBy, orderDirection, |             ctx.status = 200; | ||||
|          vacateDayStatisticStartDate: startDate, |             ctx.body = { | ||||
|          vacateDayStatisticendDate: endDate, |                 count: 0, | ||||
|          vacateDurationStatistic: true, |                 rows: [] | ||||
|          vacateCountStatistic: true, |             } | ||||
|          vacateCountStatisticStartDate: startDate, |         } else { | ||||
|          vacateCountStatisticendDate: endDate, |             const userRes = await memberList({ | ||||
|       }) |                 keywordTarget, keyword, limit, page, | ||||
| 
 |                 orderBy, orderDirection, | ||||
|       let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) |                 vacateDayStatisticStartDate: startDate, | ||||
| 
 |                 vacateDayStatisticendDate: endDate, | ||||
|       const sumRes = await vacateStatisticListDayType({ |                 vacateDurationStatistic: true, | ||||
|          startDate, endDate, pepUserIds |                 vacateCountStatistic: true, | ||||
|       }) |                 vacateCountStatisticStartDate: startDate, | ||||
| 
 |                 vacateCountStatisticendDate: endDate, | ||||
|       const remarkList = await models.VacateRemark.findAll({}); //查询备注
 |                 userIds: dataRange.userIds | ||||
| 
 |             }) | ||||
|       returnD.forEach(u => { | 
 | ||||
|          let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) |             let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) | ||||
|          let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | 
 | ||||
|          u.vacateDuration = vacateStatistic.reduce((sum, vs) => sum + vs.duration, 0) |             const sumRes = await vacateStatisticListDayType({ | ||||
|          u.vacateStatistic = vacateStatistic |                 startDate, endDate, pepUserIds | ||||
|          u.remark = remarkData.length ? remarkData[0].remark : null |             }) | ||||
|       }) | 
 | ||||
|       ctx.status = 200; |             const remarkList = await models.VacateRemark.findAll({}); //查询备注
 | ||||
|       ctx.body = { | 
 | ||||
|          count: userRes.count, |             returnD.forEach(u => { | ||||
|          rows: returnD |                 let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | ||||
|       } |                 let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | ||||
|    } catch (error) { |                 u.vacateDuration = vacateStatistic.reduce((sum, vs) => sum + vs.duration, 0) | ||||
|       ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |                 u.vacateStatistic = vacateStatistic | ||||
|       ctx.status = 400; |                 u.remark = remarkData.length ? remarkData[0].remark : null | ||||
|       ctx.body = { |             }) | ||||
|          message: typeof error == 'string' ? error : undefined |             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) { | async function exportVacateStatistic(ctx) { | ||||
|    try { |     try { | ||||
|       const { models } = ctx.fs.dc; |         const { models } = ctx.fs.dc; | ||||
|       const { clickHouse } = ctx.app.fs |         const { clickHouse } = ctx.app.fs | ||||
|       const { memberList, packageUserData, vacateStatisticListDayType, overtimeStatisticListDayType, simpleExcelDown, dayType, overtimeType } = ctx.app.fs.utils |         const { memberList, packageUserData, vacateStatisticListDayType, overtimeStatisticListDayType, simpleExcelDown, dayType, overtimeType } = ctx.app.fs.utils | ||||
|       const { |         const { | ||||
|          keywordTarget, keyword, limit, page, orderBy, orderDirection, |             keywordTarget, keyword, limit, page, orderBy, orderDirection, | ||||
|          startDate, endDate, |             startDate, endDate, | ||||
|       } = ctx.query |         } = ctx.query | ||||
| 
 | 
 | ||||
|       const vacateTypeRes = await clickHouse.hr.query(` |         const vacateTypeRes = await clickHouse.hr.query(` | ||||
|          SELECT type FROM vacate GROUP BY type ORDER BY type DESC |          SELECT type FROM vacate GROUP BY type ORDER BY type DESC | ||||
|       `).toPromise()
 |       `).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({ |             let { packageUser, pepUserIds } = await packageUserData(userRes) | ||||
|          keywordTarget, keyword, limit, page, |             returnD = packageUser; | ||||
|          orderBy, orderDirection, |             const sumRes = await vacateStatisticListDayType({ | ||||
|          vacateDayStatisticStartDate: startDate, |                 startDate, endDate, pepUserIds | ||||
|          vacateDayStatisticendDate: endDate, |             }) | ||||
|          vacateDurationStatistic: true, | 
 | ||||
|          vacateCountStatistic: true, |             const remarkList = await models.VacateRemark.findAll({}); //查询备注
 | ||||
|          vacateCountStatisticStartDate: startDate, | 
 | ||||
|          vacateCountStatisticendDate: endDate, |             returnD.forEach(u => { | ||||
|       }) |                 u.departmrnt = u.departmrnt.map(dep => dep.name).join('、') | ||||
| 
 |                 u.role = u.role.map(r => r.name).join('、') | ||||
|       let { packageUser: returnD, pepUserIds } = await packageUserData(userRes) | 
 | ||||
| 
 |                 let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) | ||||
|       const sumRes = await vacateStatisticListDayType({ |                 for (let { type } of vacateTypeRes) { | ||||
|          startDate, endDate, pepUserIds |                     u[type] = vacateStatistic.reduce((sum, v) => { | ||||
|       }) |                         if (v.type == type) { | ||||
| 
 |                             sum += v.duration / 3600 | ||||
|       const remarkList = await models.VacateRemark.findAll({}); //查询备注
 |                         } | ||||
| 
 |                         return sum | ||||
|       returnD.forEach(u => { |                     }, 0) | ||||
|          u.departmrnt = u.departmrnt.map(dep => dep.name).join('、') |                 } | ||||
|          u.role = u.role.map(r => r.name).join('、') |                 u.vacateDayStatisticDuration = (u.vacateDayStatisticDuration || 0) / 3600 | ||||
| 
 |                 u.userActiveStatus = u.userActiveStatus == 1 ? '在职' : u.userActiveStatus == 2 ? '离职' : '特殊状态-特殊账号' | ||||
|          let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) |                 let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) | ||||
|          for (let { type } of vacateTypeRes) { |                 u.remark = remarkData.length ? (remarkData[0].remark == '' ? '无' : remarkData[0].remark) : '无' | ||||
|             u[type] = vacateStatistic.reduce((sum, v) => { |             }) | ||||
|                if (v.type == type) { |         } | ||||
|                   sum += v.duration / 3600 |         const header = [{ | ||||
|                } |             title: '员工编号', | ||||
|                return sum |             key: 'userCode', | ||||
|             }, 0) |         }, { | ||||
|          } |             title: '姓名', | ||||
|          u.vacateDayStatisticDuration = (u.vacateDayStatisticDuration || 0) / 3600 |             key: 'userName', | ||||
|          u.userActiveStatus = u.userActiveStatus == 1 ? '在职' : u.userActiveStatus == 2 ? '离职' : '特殊状态-特殊账号' |         }, { | ||||
|          let remarkData = remarkList.filter(e => e.pepUserId == u.pepUserId) |             title: '所属部门', | ||||
|          u.remark = remarkData.length ? (remarkData[0].remark == '' ? '无' : remarkData[0].remark) : '无' |             key: 'departmrnt', | ||||
|       }) |         }, { | ||||
| 
 |             title: '职位', | ||||
|       const header = [{ |             key: 'role', | ||||
|          title: '员工编号', |         }, { | ||||
|          key: 'userCode', |             title: '在职状态', | ||||
|       }, { |             key: 'userActiveStatus', | ||||
|          title: '姓名', |         },] | ||||
|          key: 'userName', |             .concat(vacateTypeRes.map(v => { | ||||
|       }, { |                 return { | ||||
|          title: '所属部门', |                     title: `${v.type}请假时长(小时)`, | ||||
|          key: 'departmrnt', |                     key: v.type, | ||||
|       }, { |                     defaultValue: '0', | ||||
|          title: '职位', |                 } | ||||
|          key: 'role', |             })) | ||||
|       }, { |             .concat( | ||||
|          title: '在职状态', |                 [{ | ||||
|          key: 'userActiveStatus', |                     title: '合计请假次数(次)', | ||||
|       },] |                     key: 'vacateCount', | ||||
|          .concat(vacateTypeRes.map(v => { |                     defaultValue: '0', | ||||
|             return { |                 }, { | ||||
|                title: `${v.type}请假时长(小时)`, |                     title: '合计请假时长(小时)', | ||||
|                key: v.type, |                     key: 'vacateDayStatisticDuration', | ||||
|                defaultValue: '0', |                     defaultValue: '0', | ||||
|             } |                 }] | ||||
|          })) |             ) | ||||
|          .concat( |             .concat( | ||||
|             [{ |                 [{ | ||||
|                title: '合计请假次数(次)', |                     title: '备注', | ||||
|                key: 'vacateCount', |                     key: 'remark', | ||||
|                defaultValue: '0', |                 }] | ||||
|             }, { |             ) | ||||
|                title: '合计请假时长(小时)', | 
 | ||||
|                key: 'vacateDayStatisticDuration', |         const fileName = `请假统计_${startDate ? moment(startDate).format('YYYY-MM-DD') : ''}${startDate && endDate ? '-' : ''}${endDate ? moment(endDate).format('YYYY-MM-DD') : ''}${startDate || endDate ? '_' : ''}${moment().format('YYYYMMDDHHmmss')}` + '.csv' | ||||
|                defaultValue: '0', |         const filePath = await simpleExcelDown({ data: returnD, header, fileName: fileName }) | ||||
|             }] |         const fileData = fs.readFileSync(filePath); | ||||
|          ) | 
 | ||||
|          .concat( |         ctx.status = 200; | ||||
|             [{ |         ctx.set('Content-Type', 'application/x-xls'); | ||||
|                title: '备注', |         ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName)); | ||||
|                key: 'remark', |         ctx.body = fileData; | ||||
|             }] |     } catch (error) { | ||||
|          ) |         ctx.fs.logger.error(`path: ${ctx.path}, error: error`); | ||||
| 
 |         ctx.status = 400; | ||||
|       const fileName = `请假统计_${startDate ? moment(startDate).format('YYYY-MM-DD') : ''}${startDate && endDate ? '-' : ''}${endDate ? moment(endDate).format('YYYY-MM-DD') : ''}${startDate || endDate ? '_' : ''}${moment().format('YYYYMMDDHHmmss')}` + '.csv' |         ctx.body = { | ||||
|       const filePath = await simpleExcelDown({ data: returnD, header, fileName: fileName }) |             message: typeof error == 'string' ? error : undefined | ||||
|       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) { | async function vacateRemark(ctx) { | ||||
|    try { |     try { | ||||
|       const { models } = ctx.fs.dc; |         const { models } = ctx.fs.dc; | ||||
|       const { remark, pepUserId } = ctx.query; |         const { remark, pepUserId } = ctx.query; | ||||
|       let oldData = await models.VacateRemark.findOne({ where: { pepUserId: pepUserId } }); |         let oldData = await models.VacateRemark.findOne({ where: { pepUserId: pepUserId } }); | ||||
|       if (oldData) { |         if (oldData) { | ||||
|          await models.VacateRemark.update({ remark, pepUserId }, { where: { pepUserId: pepUserId } }); |             await models.VacateRemark.update({ remark, pepUserId }, { where: { pepUserId: pepUserId } }); | ||||
|       } else { |         } else { | ||||
|          await models.VacateRemark.create({ remark, pepUserId }); |             await models.VacateRemark.create({ remark, pepUserId }); | ||||
|       } |         } | ||||
| 
 | 
 | ||||
|       ctx.status = 200; |         ctx.status = 200; | ||||
|       ctx.body = '添加备注成功'; |         ctx.body = '添加备注成功'; | ||||
|    } catch (error) { |     } catch (error) { | ||||
|       ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |         ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); | ||||
|       ctx.status = 400; |         ctx.status = 400; | ||||
|       ctx.body = { |         ctx.body = { | ||||
|          "message": "添加备注失败" |             "message": "添加备注失败" | ||||
|       } |         } | ||||
|    } |     } | ||||
| } | } | ||||
| 
 | 
 | ||||
| module.exports = { | module.exports = { | ||||
|    overtimeStatistic, |     overtimeStatistic, | ||||
|    exportOvertimeStatistic, |     exportOvertimeStatistic, | ||||
|    vacateType, |     vacateType, | ||||
|    vacateStatistic, |     vacateStatistic, | ||||
|    exportVacateStatistic, |     exportVacateStatistic, | ||||
|    vacateRemark |     vacateRemark | ||||
| }; | }; | ||||
					Loading…
					
					
				
		Reference in new issue