'use strict'; const moment = require('moment') const fs = require('fs'); async function salesList(ctx) { try { const { memberList, packageUserData } = ctx.app.fs.utils const { keywordTarget, keyword, limit, page, state, hiredateStart, hiredateEnd, marital, native, workPlace, orderBy, orderDirection, placeSearch } = ctx.query const userRes = await memberList({ keywordTarget, keyword, limit: '', page: '', state, hiredateStart, hiredateEnd, marital, native, workPlace, orderBy, orderDirection, nowAttendanceTime: true }) let { packageUser: members } = await packageUserData(userRes, { state: true, }) const { models } = ctx.fs.dc; let res = await models.SalesDistribution.findAndCountAll({ where: { del: false }, offset: Number(page) * Number(limit), limit: Number(limit), order: [['id', 'DESC']] }) let rslt = [] res.rows.map(d => { let valid = false; let info = members.find(m => m.pepUserId == d.dataValues.pepUserId); if (info) { if (placeSearch) { let exist1 = d.dataValues.provinces.join(',').indexOf(placeSearch) != -1 let exist2 = d.dataValues.cities.join(',').indexOf(placeSearch) != -1 if (exist1 || exist2) { valid = true; } } else { valid = true; } } if (valid) { let item = { name: info.userName, userCode: info.userCode, post: info.userPost, department: info.departmrnt, hireDate: info.hiredate,//入职时间 regularDate: info.regularDate,//转正时间 ...d.dataValues } rslt.push(item); } }) ctx.status = 200; ctx.body = { count: res.count, rows: rslt }; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function add(ctx) { try { const { models } = ctx.fs.dc; const { pepUserId, provinces, cities } = ctx.request.body const existRes = await models.SalesDistribution.findOne({ where: { pepUserId } }) if (existRes && !existRes.del) { throw '当前销售人员信息已存在' } let storageData = { pepUserId, provinces, cities, del: false } if (existRes && existRes.del) { await models.SalesDistribution.update(storageData, { where: { pepUserId } }) } else { await models.SalesDistribution.create(storageData) } ctx.status = 204; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function edit(ctx) { try { const { models } = ctx.fs.dc; const { pepUserId, provinces, cities } = ctx.request.body const existRes = await models.SalesDistribution.findOne({ where: { pepUserId } }) if (!existRes) { throw '当前销售人员信息不存在' } let storageData = { pepUserId, provinces, cities, del: false } await models.SalesDistribution.update(storageData, { where: { pepUserId: pepUserId } }) ctx.status = 204; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function del(ctx) { try { const { models } = ctx.fs.dc; const { pepUserId } = ctx.query await models.SalesDistribution.update({ del: true, }, { where: { pepUserId, } }) ctx.status = 204; } catch (error) { ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = { message: typeof error == 'string' ? error : undefined } } } async function exportData(ctx) { try { const { models } = ctx.fs.dc; const { clickHouse, opts: { qiniu } } = ctx.app.fs const { simpleExcelDown, memberList, packageUserData } = ctx.app.fs.utils const { keywordTarget, keyword, limit, page, state, keys = '', hiredateStart, hiredateEnd, marital, native, workPlace, orderBy, orderDirection, } = ctx.query const userRes = await memberList({ keywordTarget, keyword, limit, page, state, hiredateStart, hiredateEnd, marital, native, workPlace, orderBy, orderDirection, nowAttendanceTime: true }) const tableAttributes = models['Member'].tableAttributes const optionKeys = keys.split(',') let { packageUser: exportD, pepUserIds } = await packageUserData(userRes) let preHeader = [{ title: '员工编号', key: 'userCode', }, { title: '姓名', key: 'userName', }] let header = [].concat(preHeader) for (let k in tableAttributes) { const comment = tableAttributes[k].comment if (k != 'id' && k != 'pepUserId' && comment) { if ([].includes(k)) { // 截住不想导出的字段 continue } header.push({ title: comment || '-', key: k, // index: tableAttributes[k].index, }) } } if (optionKeys.includes('overtimeStatistic')) { header = header.concat([{ title: '累计加班次数', key: 'overTimeCount', }, { title: '累计加班总时长 / h', key: 'overTimeDuration', },]) } if (optionKeys.includes('vacateStatistic')) { header = header.concat([{ 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 }) 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 addSalesMemberBulk(ctx) { let errorMsg = { message: '导入销售人员信息失败' }; const transaction = await ctx.fs.dc.orm.transaction(); try { const models = ctx.fs.dc.models; const data = ctx.request.body; let addArr = []; let editArr = []; let list = await models.SalesDistribution.findAll({ attributes: ['pepUserId'] }); data.map(d => { let exist = list.find(m => m.pepUserId == d.pepUserId);//项企的人员编号字段还没有 if (exist) { editArr.push(d); } else { addArr.push(d); } }) //处理新增的 if (addArr.length) { await models.SalesDistribution.bulkCreate(addArr); } //处理编辑的 if (editArr.length) { for (let i in editArr) { let { pepUserId, provinces, cities, del = false } = editArr[i]; let dataToUpdate = { provinces, cities, del } await models.SalesDistribution.update(dataToUpdate, { where: { pepUserId: pepUserId } }); } } await transaction.commit(); ctx.status = 204; } catch (error) { await transaction.rollback(); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); ctx.status = 400; ctx.body = errorMsg; } } module.exports = { salesList, add, edit, del, exportData, addSalesMemberBulk, }