
一、背景描述:
在企业日常运营中,HR系统是员工信息、考勤、人事变动等核心数据的管理平台;而泛微OA是企业内部流程审批、公文流转、协同办公的核心工具。
目前,OA已对接多套系统使用审批流程,例如费用采购流程、报销、财务、金蝶等,而当前需上HR系统进行考勤异常、请假、加班、调休等审批时,存在以下痛点:
1、系统割裂:HR 系统中产生的考勤审批数据需在 OA 中重新提交,导致重复操作。
2、效率低下:员工或 HR 需要跨系统手动发起审批,流程繁琐,易出错。
3、审批不统一:部分审批走 HR 系统,部分走 OA,缺乏统一标准和归档。
4、数据不同步:HR 系统审批通过后,OA 无记录,影响审计、合规与流程追溯。
5、领导审批负担重:审批待办分散在多个系统,难以集中处理。
为提升审批效率、实现流程统一、保障数据一致性,亟需将 HR 系统中的考勤审批业务数据自动同步推送至 OA 系统,并触发 OA 的标准审批流程。
二、解决方案:
2.1分析思路
实现思路:实现 HR 系统与 OA 系统的深度集成,使 HR 系统中产生的考勤类审批单据自动推送至 OA并自动提交,并由 OA 完成后续审批流程,审批结果回写 HR 系统。
流程集成方式:单向触发
1、HR 系统作为数据源,生成审批单后,通过接口自动推送至 OA。
2、OA 系统接收后,自动生成审批流程,进入待办。
3、审批完成后,OA 将审批结果(通过/驳回)回调 HR 系统,更新审核状态。
2.2配置OA流程关系表
首先要建立DHG系统表单发起,需调用OA的哪个流程ID,在DHG系统上维护对应关系,并支持设置人员范围,用于控制不同人员发起时,调用不同的OA流程进行审批。
这里需要建立自定义模块来进行配置。
2.3字段数据确认
1、根据OA的审批表单,确认DHG中的相关字段的取值、数据类型等。
对应的OA中,为了能实现DHG系统发起表单后自动触发OA流程提交,需要在DHG员工资料中维护OA员工ID、OA部门ID、OA公司ID。
2.4页面二开
OA提交按钮,不影响标准功能前提下,新增按钮进行配置。
表单代码二开
function submitOA(type) {
//OA用户id:creatorId、OA流程id:workflowId、hr表名:tableCode
if (this.mainForm.emp_origin_id) {
if (this.$refs.empIdSelect.empList[0].c_OAuserid && this.$refs.empIdSelect.empList[0].c_OAorgid) {
this.mainForm.creatorId = Number(this.$refs.empIdSelect.empList[0].c_OAuserid);
this.mainForm.orgOAId = Number(this.$refs.empIdSelect.empList[0].c_OAorgid);
//this.mainForm.org_name = this.$refs.empIdSelect.empList[0].org_name;
} else {
JsUlits.showWarning("请到员工档案维护该员工的OA员工id和OA部门id后重试!");
return;
}
}
//主表代码:att_business_trip_order
var res = this.syncRunCode("empHaveOaFlowInfo", { curTemplateCode: this.curTemplateCode, empOriginId: this.mainForm.c_emp_origin_id });
if (res.length > 1) {
JsUlits.showWarning("该员工未查询到OA流程信息,或者存在多笔匹配OA流程信息!");
return;
}
this.mainForm.begin_date_ymd = JsUlits.dateFormat(this.mainForm.begin_date, "yyyy-MM-dd");
this.mainForm.end_date_ymd = JsUlits.dateFormat(this.mainForm.end_date, "yyyy-MM-dd");
this.mainForm.emp_info = this.$refs.empChoose.empList[0];
this.mainForm.curTemplateCode = this.curTemplateCode;
this.mainForm.is_submit = true;
var value = this.mainForm.total_day;
var num = typeof value === 'number' ? value : parseFloat(value);
this.mainForm.total_day_fix = isNaN(num) ? "0.0" : num.toFixed(1);
this.mainForm.tableCode = this.tableCode;
this.mainForm.workflowId = res[0].c_oaflow_id;
if (!this.mainForm.audit_status || this.mainForm.audit_status == '0') {
this.mainForm.audit_status = '2';
}
this.saveLeaveOrderSelf(type);
}
function changeemphrdailiren(val) {
if (val && val.length > 0) {
this.mainForm.c_hrdailiren_name = val[0].name;
} else {
this.mainForm.c_hrdailiren_name = "";
}
}
/**
* 点击[保存]或[提交]
*
* @param type {1|2|3} 1-保存新增;2-保存退出;3-提交
*/
function saveLeaveOrderSelf(type) {
var _that = this;
// 通用校验数据
if (!_that.checkValid()) return;
// 判断请假日期范围是否存在未排班的日期
if (this.isNotSchedule) {
return _that.errMsgHandler(this.notScheduleMessage);
}
// 校验:开始日期大于结束日期, 则提示错误
_that.checkDateComparePromise()
// 保存前处理数据
.then(this.handleDataBeforeSavePromise)
// 执行保存
.then(function () {
_that.execSaveReqPromiseSelf(type)
})
.catch(_that.errMsgHandler)
}
/**
* 执行保存
*/
function execSaveReqPromiseSelf(type) {
var _that = this
// huanglb 2021/07/26 新增保存或提交; 退回提交, 都需要进行单据检查。
_that.reqCheckComplianceLeaveOrderPromise()
.then(
// handle resolve
function () {
_that.mainForm.audit_status = "2";
_that.saveQuit();
},
// handle reject
function (resultData) {
if (type) {
_that.mainForm.audit_status = "2";
_that.saveQuit();
return;
}
_that.handleExForm(_that, resultData, resultData.showConfirmButton);
}
)
}
function syncRunCode(code, param) {
var postData = {
codeType: 1,
templateId: this.curTemplateId,
code: code,
runParam: param
}
var result = null;
var url = window.ctxPath + '/sysObjectTool/runCode?curdate=' + new Date().getTime();
JsUlits.postSync(url, postData, function (res) {
result = res.data;
})
return result;
}
后台代码二开
var log = @org.slf4j.LoggerFactory.getLogger("");
var now = @com.dongbao.core.util.DateUtil.getDate();
var nowStr = @com.dongbao.core.util.DateUtil.format(now, "yyyy-MM-dd");
var tempFormData = formData.mainForm[0];
var isSuccess = "1";
var errorMsg = "";
var showParam = {};
if( tempFormData.is_self == '1'){
tempFormData = formData.mainForm[0].oa_main_form;
}
if(isEmpty(tempFormData.is_submit) && isEmpty(tempFormData.is_self) ){
return ;
}
if(isEmpty(tempFormData.code)){
//执行查询返回列表
var codeInfoList = tool.selectSql("select code from " + tempFormData.tableCode + " where id = #{id}",{id:tempFormData.id},null,null);
if(codeInfoList.~size > 0){
tempFormData.code = codeInfoList[0].code;
}
}
if (tempFormData.audit_status + "" == '2' || tempFormData.audit_status + "" == '7')
{
//判断必传参数:
if (isEmpty(tempFormData.creatorId) || isEmpty(tempFormData.workflowId) || isEmpty(tempFormData.tableCode))
{
isSuccess = "0";
errorMsg = "检查必填参数,OA用户id:creatorId、OA流程id:workflowId、hr表名:tableCode,不能为空!";
}
var urlInfo = tool.selectSql("select url from third_platform_data_source where name = 'OA代办推送服务地址'",
{}, null, null);
if (urlInfo.~size == 0 ) {
isSuccess = "0";
errorMsg = "数据源中未找到名称为‘OA代办推送服务地址’ 的数据源,请配置!";
}
if (isEmpty(tempFormData.total_day)) {
tempFormData.total_day = '0.0';
}
var hjts = tempFormData.total_day_fix + "";
if (tempFormData.end_time == "" || tempFormData.end_time == null) {
tempFormData.end_time = "23:59";
}
if (tempFormData.begin_time == "" || tempFormData.begin_time == null) {
tempFormData.begin_time = "00:00";
}
//开始附件操作
var thirdPlatformForeignControllerFile = @com.dongbao.core.util.SpringContextUtil.getBean('thirdPlatformForeignController');
var param11 = {
mainForm : tempFormData
};
var paramJson1 = @com.alibaba.fastjson.JSONObject.toJSONString(param11);
var info1 = @thirdPlatformForeignControllerFile.execBlockCode("getFileUrlCode", paramJson1);
//开始封装附件:
var fileObj = {
key : "fujian", value : "", filedType : ""
};
if (info1.~size > 0)
{
for (var ii = 0 ; ii < info1.~size ; ii++ )
{
var item = info1[ii];
if (ii != 0)
{
fileObj.value = fileObj.value + "|" + info1[ii].fileUrl;
fileObj.filedType = fileObj.filedType + "|http:" + info1[ii].fileName;
}else {
fileObj.value = info1[ii].fileUrl;
fileObj.filedType = "http:" + info1[ii].fileName;
}
}
}
var param =
{
// 基本流程信息
"creatorId" : tempFormData.creatorId, // OA的用户id (number类型)
"workflowId" : tempFormData.workflowId, // OA的流程id (string类型)
"isNextflow" : "0", // 是否自动提交下一流程 (string类型)
"requestName" : "请假申请单-" + tempFormData.code + "-" + tempFormData.emp_info.name + "-" + nowStr , // 流程标题 (string类型)
"endpointUrl" : urlInfo[0].url, // WebService地址
"tableCode" : tempFormData.tableCode, "requestId" : "", "type" : "submit", "submitRemark" : " ",
"id" : tempFormData.id, // 主表数据
"mainTableData" :
{
"title" : "请假申请单-" + tempFormData.code + "-" + tempFormData.emp_info.name + "-" + nowStr , // 流程标题
"sqr" : tempFormData.creatorId + "", // 申请人,用户id
"sqbm": tempFormData.orgOAId + "", // 申请部门,不用传值
"sqsj" : nowStr, // 申请日期,格式 YYYY-MM-DD
"hrdailiren" : tempFormData.c_hrdailiren_name,
// "lcbh": "", // 流程编号,不用传值
// --- 业务单据字段 (属于主表) ---
"hrgh" : tempFormData.emp_info.emp_no, // 请假人工号
"hrxm" : tempFormData.emp_info.name, // 请假人姓名
"lianluofangshi" : tempFormData.e