From 4e0b12031e162cfb91814591f3835752d1dc1345 Mon Sep 17 00:00:00 2001 From: "gao.zhiyuan" Date: Mon, 17 Oct 2022 11:16:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=BA=E5=91=98id=E6=A8=A1=E7=B3=8A=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/member/index.js | 59 +++- api/app/lib/index.js | 1 + api/app/lib/models/member.js | 418 ++++++++++++------------ api/app/lib/utils/member.js | 4 +- api/config.js | 6 + 5 files changed, 274 insertions(+), 214 deletions(-) diff --git a/api/app/lib/controllers/member/index.js b/api/app/lib/controllers/member/index.js index 1b04d2d..7dc5243 100644 --- a/api/app/lib/controllers/member/index.js +++ b/api/app/lib/controllers/member/index.js @@ -221,7 +221,7 @@ async function list (ctx) { ) .replace(/_/g, '') } - obj[nextKey] = u[k] + obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' ? null : u[k] } returnD.push({ ...obj, @@ -234,7 +234,7 @@ async function list (ctx) { name: u.roleName }] : [], del: undefined, - pepuserid: undefined + pepuserid: undefined, }) } }) @@ -382,6 +382,7 @@ async function vacateStatistics (ctx) { async function exportData (ctx) { try { const { models } = ctx.fs.dc; + const { clickHouse, opts: { qiniu } } = ctx.app.fs const { simpleExcelDown, memberList } = ctx.app.fs.utils const { keywordTarget, keyword, limit, page, state, keys = '' } = ctx.query @@ -391,6 +392,7 @@ async function exportData (ctx) { const optionKeys = keys.split(',') let exportD = [] + let pepUserIds = [] userRes.forEach(u => { let existUser = exportD.find(r => r.pepUserId == u.pepUserId) if (existUser) { @@ -419,8 +421,9 @@ async function exportData (ctx) { ) .replace(/_/g, '') } - obj[nextKey] = u[k] + obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' ? null : u[k] } + pepUserIds.push(u.pepUserId) exportD.push({ ...obj, departmrnt: u.depId ? [{ @@ -456,6 +459,56 @@ async function exportData (ctx) { }) } } + header = header.concat([{ + title: '累计加班次数', + key: 'overTimeCount', + }, { + title: '累计加班总时长 / h', + key: 'overTimeDuration', + }, { + 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.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 }) diff --git a/api/app/lib/index.js b/api/app/lib/index.js index 231b570..5ff39cf 100644 --- a/api/app/lib/index.js +++ b/api/app/lib/index.js @@ -16,6 +16,7 @@ module.exports.entry = function (app, router, opts) { app.fs.logger.log('info', '[FS-AUTH]', 'Inject auth and api mv into router.'); app.fs.api = app.fs.api || {}; + app.fs.opts = opts || {}; app.fs.utils = app.fs.utils || {}; app.fs.api.authAttr = app.fs.api.authAttr || {}; app.fs.api.logAttr = app.fs.api.logAttr || {}; diff --git a/api/app/lib/models/member.js b/api/app/lib/models/member.js index a3d4df6..56f7048 100644 --- a/api/app/lib/models/member.js +++ b/api/app/lib/models/member.js @@ -2,213 +2,213 @@ 'use strict'; module.exports = dc => { - const DataTypes = dc.ORM; - const sequelize = dc.orm; - const Member = sequelize.define("member", { - pepUserId: { - type: DataTypes.INTEGER, - allowNull: false, - defaultValue: null, - comment: "项企用户id", - primaryKey: true, - field: "pep_user_id", - autoIncrement: false, - unique: "member_pep_user_id_uindex" - }, - idNumber: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "证件号", - primaryKey: false, - field: "id_number", - autoIncrement: false - }, - idPhoto: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "证件照", - primaryKey: false, - field: "id_photo", - autoIncrement: false - }, - gender: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "性别", - primaryKey: false, - field: "gender", - autoIncrement: false - }, - birthday: { - type: DataTypes.DATEONLY, - allowNull: true, - defaultValue: null, - comment: "出生年月", - primaryKey: false, - field: "birthday", - autoIncrement: false - }, - nativePlace: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "籍贯", - primaryKey: false, - field: "native_place", - autoIncrement: false - }, - marital: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "婚育状态", - primaryKey: false, - field: "marital", - autoIncrement: false - }, - politicsStatus: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "整治面貌", - primaryKey: false, - field: "politics_status", - autoIncrement: false - }, - phoneNumber: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "phone_number", - autoIncrement: false - }, - workPlace: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "工作地点", - primaryKey: false, - field: "work_place", - autoIncrement: false - }, - graduatedFrom: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "毕业院校", - primaryKey: false, - field: "graduated_from", - autoIncrement: false - }, - educationBackground: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "学历", - primaryKey: false, - field: "education_background", - autoIncrement: false - }, - specialty: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "专业", - primaryKey: false, - field: "specialty", - autoIncrement: false - }, - graduationDate: { - type: DataTypes.DATEONLY, - allowNull: true, - defaultValue: null, - comment: "毕业时间", - primaryKey: false, - field: "graduation_date", - autoIncrement: false - }, - hiredate: { - type: DataTypes.DATEONLY, - allowNull: true, - defaultValue: null, - comment: "入职时间", - primaryKey: false, - field: "hiredate", - autoIncrement: false - }, - turnProbationPeriod: { - type: DataTypes.DATEONLY, - allowNull: true, - defaultValue: null, - comment: "转试用期时间", - primaryKey: false, - field: "turn_probation_period", - autoIncrement: false - }, - regularDate: { - type: DataTypes.DATEONLY, - allowNull: true, - defaultValue: null, - comment: "转正时间", - primaryKey: false, - field: "regular_date", - autoIncrement: false - }, - dimissionDate: { - type: DataTypes.DATEONLY, - allowNull: true, - defaultValue: null, - comment: "离职时间", - primaryKey: false, - field: "dimission_date", - autoIncrement: false - }, - experienceYear: { - type: DataTypes.INTEGER, - allowNull: true, - defaultValue: null, - comment: "工作经验/年", - primaryKey: false, - field: "experience_year", - autoIncrement: false - }, - occupationalHistory: { - type: DataTypes.TEXT, - allowNull: true, - defaultValue: null, - comment: "工作经历", - primaryKey: false, - field: "occupational_history", - autoIncrement: false - }, - vitae: { - type: DataTypes.STRING, - allowNull: true, - defaultValue: null, - comment: "简历", - primaryKey: false, - field: "vitae", - autoIncrement: false - }, - del: { - type: DataTypes.BOOLEAN, - allowNull: true, - defaultValue: null, - comment: null, - primaryKey: false, - field: "del", - autoIncrement: false - } - }, { - tableName: "member", - comment: "", - indexes: [] - }); - dc.models.Member = Member; - return Member; + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const Member = sequelize.define("member", { + pepUserId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: "项企用户id", + primaryKey: true, + field: "pep_user_id", + autoIncrement: false, + unique: "member_pep_user_id_uindex" + }, + idNumber: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "证件号", + primaryKey: false, + field: "id_number", + autoIncrement: false + }, + idPhoto: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "证件照", + primaryKey: false, + field: "id_photo", + autoIncrement: false + }, + gender: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "性别", + primaryKey: false, + field: "gender", + autoIncrement: false + }, + birthday: { + type: DataTypes.DATEONLY, + allowNull: true, + defaultValue: null, + comment: "出生年月", + primaryKey: false, + field: "birthday", + autoIncrement: false + }, + nativePlace: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "籍贯", + primaryKey: false, + field: "native_place", + autoIncrement: false + }, + marital: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "婚育状态", + primaryKey: false, + field: "marital", + autoIncrement: false + }, + politicsStatus: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "整治面貌", + primaryKey: false, + field: "politics_status", + autoIncrement: false + }, + phoneNumber: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: '手机号码', + primaryKey: false, + field: "phone_number", + autoIncrement: false + }, + workPlace: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "工作地点", + primaryKey: false, + field: "work_place", + autoIncrement: false + }, + graduatedFrom: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "毕业院校", + primaryKey: false, + field: "graduated_from", + autoIncrement: false + }, + educationBackground: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "学历", + primaryKey: false, + field: "education_background", + autoIncrement: false + }, + specialty: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "专业", + primaryKey: false, + field: "specialty", + autoIncrement: false + }, + graduationDate: { + type: DataTypes.DATEONLY, + allowNull: true, + defaultValue: null, + comment: "毕业时间", + primaryKey: false, + field: "graduation_date", + autoIncrement: false + }, + hiredate: { + type: DataTypes.DATEONLY, + allowNull: true, + defaultValue: null, + comment: "入职时间", + primaryKey: false, + field: "hiredate", + autoIncrement: false + }, + turnProbationPeriod: { + type: DataTypes.DATEONLY, + allowNull: true, + defaultValue: null, + comment: "转试用期时间", + primaryKey: false, + field: "turn_probation_period", + autoIncrement: false + }, + regularDate: { + type: DataTypes.DATEONLY, + allowNull: true, + defaultValue: null, + comment: "转正时间", + primaryKey: false, + field: "regular_date", + autoIncrement: false + }, + dimissionDate: { + type: DataTypes.DATEONLY, + allowNull: true, + defaultValue: null, + comment: "离职时间", + primaryKey: false, + field: "dimission_date", + autoIncrement: false + }, + experienceYear: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: "工作经验/年", + primaryKey: false, + field: "experience_year", + autoIncrement: false + }, + occupationalHistory: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: null, + comment: "工作经历", + primaryKey: false, + field: "occupational_history", + autoIncrement: false + }, + vitae: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "简历", + primaryKey: false, + field: "vitae", + autoIncrement: false + }, + del: { + type: DataTypes.BOOLEAN, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "del", + autoIncrement: false + } + }, { + tableName: "member", + comment: "", + indexes: [] + }); + dc.models.Member = Member; + return Member; }; \ No newline at end of file diff --git a/api/app/lib/utils/member.js b/api/app/lib/utils/member.js index f5b2806..48dc307 100644 --- a/api/app/lib/utils/member.js +++ b/api/app/lib/utils/member.js @@ -67,7 +67,7 @@ module.exports = function (app, opts) { INNER JOIN ${pepEmis}.user AS user ON member.pep_user_id = user.id ${keywordTarget == 'number' && keyword ? ` - AND user.id LIKE '%${keyword}%' + AND toString(user.id) LIKE '%${keyword}%' `: ''} ${keywordTarget == 'name' && keyword ? ` AND user.name LIKE '%${keyword}%' @@ -138,7 +138,7 @@ module.exports = function (app, opts) { ${whereOption.length ? `WHERE ${whereOption.join(' AND ')}` : ''} `).toPromise() - + return userRes } diff --git a/api/config.js b/api/config.js index ef18ba1..8956cf9 100644 --- a/api/config.js +++ b/api/config.js @@ -107,6 +107,12 @@ const product = { 'INTERNALLY_TERMINATED' //流程异常结束 ] }, + qiniu: { + domain: QINIU_DOMAIN_QNDMN_RESOURCE, + bucket: QINIU_BUCKET_RESOURCE, + accessKey: QINIU_AK, + secretKey: QINIU_SK + }, redis: { host: IOTA_REDIS_SERVER_HOST, port: IOTA_REDIS_SERVER_PORT,