diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index 7ae1e3a..56205c3 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -38,12 +38,9 @@ // "--clickHouseUser ", // "--clickHousePassword ", - // 研发 - // "--clickHousePepEmis pepca", - // 测试 "--clickHousePepEmis pepca8", - + "--clickHouseCamworkflow camworkflow", ] }, { diff --git a/api/app/lib/controllers/member/index.js b/api/app/lib/controllers/member/index.js index eb54225..4e6f61d 100644 --- a/api/app/lib/controllers/member/index.js +++ b/api/app/lib/controllers/member/index.js @@ -97,6 +97,7 @@ async function searchPepMember (ctx) { }) } }) + ctx.status = 200; ctx.body = returnD } catch (error) { diff --git a/api/app/lib/models/holiday.js b/api/app/lib/models/holiday.js new file mode 100644 index 0000000..622412f --- /dev/null +++ b/api/app/lib/models/holiday.js @@ -0,0 +1,34 @@ +/* eslint-disable*/ +'use strict'; + +module.exports = dc => { + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const Holiday = sequelize.define("holiday", { + day: { + type: DataTypes.DATEONLY, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: true, + field: "day", + autoIncrement: false, + unique: "holiday_day_uindex" + }, + holiday: { + type: DataTypes.JSONB, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "holiday", + autoIncrement: false + } + }, { + tableName: "holiday", + comment: "", + indexes: [] + }); + dc.models.Holiday = Holiday; + return Holiday; +}; \ No newline at end of file diff --git a/api/app/lib/models/overtime.js b/api/app/lib/models/overtime.js new file mode 100644 index 0000000..61c6787 --- /dev/null +++ b/api/app/lib/models/overtime.js @@ -0,0 +1,142 @@ +/* eslint-disable*/ +'use strict'; + +module.exports = dc => { + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const Overtime = sequelize.define("overtime", { + id: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: true, + field: "id", + autoIncrement: true, + unique: "overtime_id_uindex" + }, + pepUserId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "pep_user_id", + autoIncrement: false + }, + startTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "start_time", + autoIncrement: false + }, + endTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "end_time", + autoIncrement: false + }, + duration: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "duration", + autoIncrement: false + }, + pepProcessStoryId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "pep_process_story_id", + autoIncrement: false + }, + wfProcessState: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "wf_process_state", + autoIncrement: false + }, + takeRestWorkday: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: "0", + comment: "工作日调休", + primaryKey: false, + field: "take_rest_workday", + autoIncrement: false + }, + takeRestDayoff: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: "0", + comment: "普假调休", + primaryKey: false, + field: "take_rest_dayoff", + autoIncrement: false + }, + takeRestFestivals: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: "0", + comment: "节假日调休", + primaryKey: false, + field: "take_rest_festivals", + autoIncrement: false + }, + payWorkday: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: "0", + comment: "工作日补偿", + primaryKey: false, + field: "pay_workday", + autoIncrement: false + }, + payDayoff: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: "0", + comment: "普假补偿", + primaryKey: false, + field: "pay_dayoff", + autoIncrement: false + }, + payFestivals: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: "0", + comment: "节假日补偿", + primaryKey: false, + field: "pay_festivals", + autoIncrement: false + }, + compensate: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "补偿方式", + primaryKey: false, + field: "compensate", + autoIncrement: false + } + }, { + tableName: "overtime", + comment: "", + indexes: [] + }); + dc.models.Overtime = Overtime; + return Overtime; +}; \ No newline at end of file diff --git a/api/app/lib/models/vacate.js b/api/app/lib/models/vacate.js new file mode 100644 index 0000000..7a89132 --- /dev/null +++ b/api/app/lib/models/vacate.js @@ -0,0 +1,88 @@ +/* eslint-disable*/ +'use strict'; + +module.exports = dc => { + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const Vacate = sequelize.define("vacate", { + id: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: true, + field: "id", + autoIncrement: true, + unique: "vacate_id_uindex" + }, + pepUserId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "pep_user_id", + autoIncrement: false + }, + startTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "start_time", + autoIncrement: false + }, + endTime: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "end_time", + autoIncrement: false + }, + type: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "请假类别", + primaryKey: false, + field: "type", + autoIncrement: false + }, + duration: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: "时长 s", + primaryKey: false, + field: "duration", + autoIncrement: false + }, + pepProcessStoryId: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: "和 项企 workflow_process_history 关联", + primaryKey: false, + field: "pep_process_story_id", + autoIncrement: false + }, + wfProcessState: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: "流程状态", + primaryKey: false, + field: "wf_process_state", + autoIncrement: false + } + }, { + tableName: "vacate", + comment: "", + indexes: [] + }); + dc.models.Vacate = Vacate; + return Vacate; +}; \ No newline at end of file diff --git a/api/app/lib/schedule/attendance.js b/api/app/lib/schedule/attendance.js new file mode 100644 index 0000000..7e72c81 --- /dev/null +++ b/api/app/lib/schedule/attendance.js @@ -0,0 +1,429 @@ +const schedule = require('node-schedule'); +const moment = require('moment') + +module.exports = function (app, opts) { + const updateAttendance = app.fs.scheduleInit( + // 妥妥流水账 (*^▽^*) + { + interval: '34 21 4 * * *', + // interval: '*/3 * * * *', + // immediate: true, + // proRun: true, + }, + async () => { + console.info('假勤数据更新 ', moment().format('YYYY-MM-DD HH:mm:ss')); + const { workFlow: { processState } } = opts + try { + const startTime = moment() + const { models } = app.fs.dc + const { judgeHoliday } = app.fs.utils + const { clickHouse } = app.fs + const { database: camWorkflow } = clickHouse.camWorkflow.opts.config + const { } = app.fs.utils + + let overtimeNeedData = { + begainTime: { + keyWord: ['加班开始时间'], + require: true, + }, + endTime: { + keyWord: ['加班结束时间'], + require: true, + }, + duration: { + keyWord: ['总时长(小时)'] + }, + compensate: { + keyWord: ['加班补偿'], + require: true, + }, + hrAffirmDuration: { + keyWord: ['人事核定加班小时', '核定加班小时'], + require: true, + }, + } + + let vacateNeedData = { + begainTime: { + keyWord: ['请假开始时间', '请假起始时间'], + keys: ['leaveStartTime'], + require: true, + }, + endTime: { + keyWord: ['请假结束时间', '请假终止时间'], + keys: ['leaveEndTime'], + require: true, + }, + type: { + keyWord: ['请假类别', '请假类型'], + keys: ['leaveType'], + require: true, + }, + hrAffirmType: { + keyWord: ['核定请假类别'], + }, + duration: { + keyWord: ['请假时长(小时)', '请假小时'], + keys: ['leaveTime'] + }, + hrAffirmDuration: { + keyWord: ['核定请假小时'], + }, + } + + const schemaRecursionObj = ({ + jsonSchema, keyWord, targetKeys = [], schemaPath, require + }) => { + let schemaPath_ = JSON.parse(JSON.stringify(schemaPath)) + if (jsonSchema.properties) { + for (let prKey in jsonSchema.properties) { + if ( + keyWord.includes(jsonSchema.properties[prKey].title) + || targetKeys.includes(prKey) + ) { + schemaPath_.push({ + prKey, + ...jsonSchema.properties[prKey] + }) + return schemaPath_ + } else if (jsonSchema.properties[prKey].properties) { + schemaPath_.push({ + prKey, + ...jsonSchema.properties[prKey] + }) + schemaPath_ = schemaRecursionObj({ + jsonSchema: jsonSchema.properties[prKey], + keyWord, + targetKeys, + schemaPath: schemaPath_, + require, + }) + if (!schemaPath_.length && require) { + console.warn('数据字段查找错误:', jsonSchema.properties); + } + if (schemaPath_.length > schemaPath.length) { + return schemaPath_ + } + } + } + } else { + return schemaPath_ + } + } + + const dataRecursionObj = (dataObj, index, needData, lastKeyObj, nd) => { + const keyObj = needData[nd].schemaPath[index] + if (dataObj.hasOwnProperty(keyObj.prKey)) { + if (lastKeyObj.prKey == keyObj.prKey) { + let gotValue = dataObj[keyObj.prKey] + if (keyObj.enum) { + let vIndex = keyObj.enum.findIndex(ke => ke == gotValue) + gotValue = keyObj.enumNames[vIndex] + } + return gotValue + } else { + return dataRecursionObj( + dataObj[keyObj.prKey], + index + 1, + needData, + lastKeyObj, + nd + ) + } + } + } + + const getData = (applyDetail, needData) => { + for (let nd in needData) { + if (needData[nd].noProcess) { + continue + } + if (applyDetail.formSchema) { + const { jsonSchema } = JSON.parse(applyDetail.formSchema) + needData[nd].schemaPath = schemaRecursionObj({ + jsonSchema: jsonSchema || {}, + keyWord: needData[nd]['keyWord'], + targetKeys: needData[nd]['keys'], + schemaPath: [], + require: nd.require + }) + if ( + needData[nd].schemaPath + && needData[nd].schemaPath.length + ) { + const lastKeyObj = needData[nd] + .schemaPath[needData[nd].schemaPath.length - 1] + if (applyDetail.formData) { + const formData = JSON.parse(applyDetail.formData) + needData[nd].value = dataRecursionObj( + formData, 0, needData, lastKeyObj, nd + ) + } else { + console.warn( + `表单数据缺失:`, + applyDetail + ); + } + } else { + if (needData[nd].require) { + // 记录错误 关键数据没找到 + console.warn( + `数据字段查找错误:${nd.needData[nd]['keyWord'].join('、')}`, + jsonSchema + ); + } + } + } + } + } + + + const attendanceRes = await clickHouse.pepEmis.query( + ` + SELECT + story.id AS historyId, + story.apply_user AS pepUserId, + story.form_data AS formData, + story.submit_form_data AS submitFormData, + fform.form_schema AS formSchema, + fprocess.name AS processName, + procin.state_ AS state, + fform.id AS formId + ` + + + `,fversion.id AS versionId` + + `,fgroup.name AS groupName` + + ` + FROM + workflow_process_history AS story + INNER JOIN workflow_process_version AS fversion + ON fversion.id = story.version_id + INNER JOIN workflow_process_form AS fform + ON fform.id = fversion.form_id + INNER JOIN workflow_process AS fprocess + ON fprocess.id = fform.process_id + INNER JOIN workflow_group AS fgroup + ON fgroup.id = fprocess.group_id + AND fgroup.name = '假勤管理' + INNER JOIN ${camWorkflow}.act_hi_procinst AS procin + ON procin.id_ = story.procinst_id + ` + ).toPromise() + + let insertCount = 0, updateCount = 0, invalidCount = 0, unCompletedCount = 0, unknowCount = 0 + for (let a of attendanceRes) { + console.log(`处理 ${a.pepUserId}·s ${a.processName}(form:${a.formId} story:${a.historyId}) `); + if (a.processName) { + if ('COMPLETED' == a.state) { + if (a.processName.indexOf('请假') > -1) { + let needData = JSON.parse(JSON.stringify(vacateNeedData)) + getData(a, needData) + const { begainTime, endTime, type, hrAffirmType, duration, hrAffirmDuration } = needData + if (begainTime.value && endTime.value && type.value) { + let durationSec = 0 + if (hrAffirmDuration.value) { + durationSec = parseFloat(hrAffirmDuration.value) * 3600 + } else if (duration.value) { + durationSec = parseFloat(duration.value) * 3600 + } else { + durationSec = moment(endTime.value).diff(moment(begainTime.value), 'second') + } + if (typeof durationSec != 'number' || isNaN(durationSec) || durationSec <= 0) { + console.warn('请假时长计算结果错误', hrAffirmDuration, duration); + invalidCount++ + } else { + + let typeStorage = '' + if (hrAffirmType.value) { + typeStorage = hrAffirmType.value + } else { + typeStorage = type.value + } + + const existRes = await models.Vacate.findOne({ + where: { + pepProcessStoryId: a.historyId + } + }) + let storageD = { + pepUserId: a.pepUserId, + pepProcessStoryId: a.historyId, + startTime: moment(begainTime.value).format('YYYY-MM-DD HH:mm:ss'), + endTime: moment(endTime.value).format('YYYY-MM-DD HH:mm:ss'), + duration: durationSec, + type: typeStorage, + wfProcessState: a.state, + } + if (existRes) { + await models.Vacate.update(storageD, { + where: { + id: existRes.id + } + }) + updateCount++ + } else { + await models.Vacate.create(storageD) + insertCount++ + } + } + } else { + console.warn('必填 value 缺失:', needData,); + console.warn('流程数据:', a); + invalidCount++ + } + } else if (a.processName.indexOf('加班') > -1) { + // 深拷贝所需查询数据 + let needData = JSON.parse(JSON.stringify(overtimeNeedData)) + // 获取表单里的数据并插入 needData + getData(a, needData) + + const { begainTime, endTime, duration, compensate, hrAffirmDuration } = needData + + if (begainTime.value && endTime.value && hrAffirmDuration.value && compensate.value) { + let durationSec = parseFloat(hrAffirmDuration.value) * 3600 + + if (typeof durationSec != 'number' || isNaN(durationSec || durationSec <= 0)) { + console.warn('加班时长计算结果错误', duration); + invalidCount++ + } else { + // 开始时间 + let begainTime_ = moment(begainTime.value) + // 加上人事确定的时间的结束时间 + let endTimeWithHrAffirm = begainTime_.clone().add(durationSec, 'seconds') + // 定义需要统计的各类变量 + let takeRestWorkday = 0, + takeRestDayoff = 0, + takeRestFestivals = 0, + payWorkday = 0, + payDayoff = 0, + payFestivals = 0 + + // 判断 结束时间在加班当天的时间节点后 也就是说跨天加班了 + if (endTimeWithHrAffirm.isSameOrAfter(begainTime_)) { + let packageSuccess = true + // 考虑加了好多天的流程 + let curday = begainTime_.clone() + while (curday.isSameOrBefore(endTimeWithHrAffirm)) { + let duration_ = 0 + if (curday.isSame(endTimeWithHrAffirm, 'day')) { + // 是同一天 + duration_ = endTimeWithHrAffirm.diff(curday, 'seconds') + } else if (curday.isSame(begainTime_, 'day')) { + // 和开始日期是同一天 + // 同时也说明和结束日期不是同一天 + duration_ = begainTime_.clone() + .endOf('day') + .diff(begainTime_, 'seconds') + 1 + } else { + // 跨了好几天 + // 不但 curday 加 后一天也加 + duration_ = 24 * 3600 + } + const holidayRes = await judgeHoliday(curday.format('YYYY-MM-DD')) + if (holidayRes) { + if (compensate.value && compensate.value.indexOf('调休') >= 0) { + if (holidayRes.workday) { + takeRestWorkday += duration_ + } else if (holidayRes.dayoff) { + takeRestDayoff += duration_ + } else if (holidayRes.festivals) { + takeRestFestivals += duration_ + } else { + let a = 4 + } + } else if (compensate.value && compensate.value.indexOf('补偿') >= 0) { + if (holidayRes.workday) { + payWorkday += duration_ + } else if (holidayRes.dayoff) { + payDayoff += duration_ + } else if (holidayRes.festivals) { + payFestivals += duration_ + } + } else { + console.warn(`加班补偿字段未知:`, compensate.value); + invalidCount++ + packageSuccess = false + break + } + } else { + console.warn(`节假日信息获取失败`, curday.format('YYYY-MM-DD')); + invalidCount++ + packageSuccess = false + break + } + curday = curday.add(1, 'day').startOf('day') + } + if (packageSuccess) { + const existRes = await models.Overtime.findOne({ + where: { + pepProcessStoryId: a.historyId + } + }) + let storageD = { + pepUserId: a.pepUserId, + pepProcessStoryId: a.historyId, + startTime: moment(begainTime.value).format('YYYY-MM-DD HH:mm:ss'), + endTime: moment(endTime.value).format('YYYY-MM-DD HH:mm:ss'), + duration: durationSec, + wfProcessState: a.state, + takeRestWorkday, + takeRestDayoff, + takeRestFestivals, + payWorkday, + payDayoff, + payFestivals, + compensate: compensate.value + } + if (existRes) { + await models.Overtime.update(storageD, { + where: { + id: existRes.id + } + }) + updateCount++ + } else { + await models.Overtime.create(storageD) + insertCount++ + } + } + } else { + console.warn(`结束时间在开始时间之前(unbelievable)`, '开始' + begainTime.value, '结束' + endTime.value, '人事确认结束' + endTimeWithHrAffirm.format()); + invalidCount++ + } + } + } else { + console.warn('必填 value 缺失:', needData,); + console.warn('流程数据:', a); + invalidCount++ + } + } else { + console.warn('假勤分组内不明流程'); + unknowCount++ + } + } else { + unCompletedCount++ + } + } else { + invalidCount++ + } + } + + console.info(` + 假勤数据更新 用时 ${moment().diff(startTime, 'seconds')} s + `) + console.info(` + 共:${attendanceRes.length}; + 新增:${insertCount}; + 更新数据:${updateCount}; + 非完成状态流程:${unCompletedCount}; + 不明流程:${unknowCount}; + 无效(warning):${invalidCount}; + `); + } catch (error) { + app.fs.logger.error(`sechedule: updateAttendance, error: ${error}`); + } + }); + return { + updateAttendance, + } +} \ No newline at end of file diff --git a/api/app/lib/schedule/timor_holiday.js b/api/app/lib/schedule/timor_holiday.js new file mode 100644 index 0000000..d32af9f --- /dev/null +++ b/api/app/lib/schedule/timor_holiday.js @@ -0,0 +1,59 @@ +'use strict'; +const moment = require('moment'); +const request = require('superagent'); + +module.exports = function (app, opts) { + const timorHoliday = app.fs.scheduleInit( + { + interval: '54 42 4 */7 * * *', + // immediate: true, + proRun: true, + }, + async () => { + const { timorApiUrl } = opts + const { models } = app.fs.dc + + const existCount = await models.Holiday.count() + + let begainDay = existCount ? moment() : moment('2022-01-01') + let endDay = moment().add(3, 'months').endOf('month') + let checkDay = begainDay.clone() + while (checkDay.isSameOrBefore(endDay)) { + try { + const checkDayStr = checkDay.format('YYYY-MM-DD') + let holidayRes = await request.get( + timorApiUrl + `holiday/info/${checkDayStr}`, + ) + let holidayData = holidayRes.body || {} + if (holidayData.code == 0) { + const dbRes = await models.Holiday.findOne({ + where: { + day: checkDayStr + } + }) + if (dbRes) { + await models.Holiday.update({ holiady: holidayData }, { + where: { + day: checkDayStr + } + }) + } else { + await models.Holiday.create({ + day: checkDayStr, + holiady: holidayData + }) + } + } + checkDay = checkDay.add(1, 'day') + } catch (error) { + console.error(error); + // TODO 发邮件 + } + } + } + ) + + return { + timorHoliday + } +} \ No newline at end of file diff --git a/api/app/lib/utils/days.js b/api/app/lib/utils/days.js new file mode 100644 index 0000000..37c6f92 --- /dev/null +++ b/api/app/lib/utils/days.js @@ -0,0 +1,65 @@ +'use strict'; +const moment = require('moment') +const request = require('superagent'); + +module.exports = function (app, opts) { + + async function judgeHoliday (dayStr) { + const { timorApiUrl } = opts + const { models } = app.fs.dc + let dayStr_ = dayStr || moment().format('YYYY-MM-DD') + let holidayData = null + const dbRes = await models.Holiday.findOne({ + where: { + day: dayStr_ + } + }) + if (dbRes) { + holidayData = dbRes.dataValues.holiday + } else { + let holidayRes = await request.get( + timorApiUrl + `holiday/info/${dayStr_}` + ) + holidayData = holidayRes.body || {} + } + + if (holidayData && holidayData.code == 0) { + let returnD = { + workday: false, + dayoff: false, + festivals: false, + params: holidayData.type + } + let holidayType = holidayData.type.type + if ( + holidayType == 2 + && holidayData.holiday + && holidayData.holiday.wage == 3 + ) { + // 正经节假日 3倍工资那种 + // festivals + returnD.festivals = true + } else if ( + holidayType == 1 + || ( + holidayType == 2 + && holidayData.holiday + && holidayData.holiday.wage < 3 + ) + ) { + // 普假 休息日非节假日 + returnD.dayoff = true + } else if (holidayType == 0 || holidayType == 3) { + // 工作日或补班 + returnD.workday = true + } + return returnD + } else { + return false + } + } + + return { + judgeHoliday + } +} \ No newline at end of file diff --git a/api/config.js b/api/config.js index c8c7345..7f5b2c5 100644 --- a/api/config.js +++ b/api/config.js @@ -28,6 +28,7 @@ args.option('qndmn', 'qiniuDomain'); args.option('clickHouseUrl', 'clickHouse Url'); args.option('clickHousePort', 'clickHouse Port'); args.option('clickHousePepEmis', 'clickHouse 项企数据库名称'); +args.option('clickHouseCamworkflow', 'clickHouse 工作流数据库名称'); const flags = args.parse(process.argv); @@ -54,6 +55,10 @@ const CLICKHOUST_PORT = process.env.CLICKHOUST_PORT || flags.clickHousePort const CLICKHOUST_USER = process.env.CLICKHOUST_USER || flags.clickHouseUser const CLICKHOUST_PASSWORD = process.env.CLICKHOUST_PASSWORD || flags.clickHousePassword const CLICKHOUST_PEP_EMIS = process.env.CLICKHOUST_PEP_EMIS || flags.clickHousePepEmis +const CLICKHOUST_CAM_WORKFLOW = process.env.CLICKHOUST_CAM_WORKFLOW || flags.clickHouseCamworkflow + +// timor 节假日查询 +const API_TIMOR_URL = 'http://timor.tech/api/' if ( !POMS_DB @@ -61,7 +66,7 @@ if ( || !API_EMIS_URL || !QINIU_DOMAIN_QNDMN_RESOURCE || !QINIU_BUCKET_RESOURCE || !QINIU_AK || !QINIU_SK || !CLICKHOUST_URL || !CLICKHOUST_PORT - || !CLICKHOUST_PEP_EMIS + || !CLICKHOUST_PEP_EMIS || !CLICKHOUST_CAM_WORKFLOW ) { console.log('缺少启动参数,异常退出'); args.showHelp(); @@ -90,6 +95,16 @@ const product = { exclude: [ ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 + workFlow: { + processState: [ + 'WAIT', //保存待发 + 'ACTIVE', // 正在运行中 + 'SUSPENDED', // 流程暂停 + 'COMPLETED', //流程正常结束 + 'EXTERNALLY_TERMINATED', // 手动结束流程 + 'INTERNALLY_TERMINATED' //流程异常结束 + ] + }, redis: { host: IOTA_REDIS_SERVER_HOST, port: IOTA_REDIS_SERVER_PORT, @@ -110,6 +125,7 @@ const product = { password: 'Fs2689' } }, + timorApiUrl: API_TIMOR_URL, pssaRequest: [{ name: 'emisRequest', root: API_EMIS_URL @@ -123,6 +139,10 @@ const product = { { name: 'pepEmis', db: CLICKHOUST_PEP_EMIS + }, + { + name: 'camWorkflow', + db: CLICKHOUST_CAM_WORKFLOW } ] } diff --git a/api/sequelize-automate.config.js b/api/sequelize-automate.config.js index 3c6744b..e3207cc 100644 --- a/api/sequelize-automate.config.js +++ b/api/sequelize-automate.config.js @@ -26,7 +26,7 @@ module.exports = { dir: './app/lib/models', // 指定输出 models 文件的目录 typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义 emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir` - tables: ['member'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 + tables: ['overtime'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性 skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性 tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中 ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面