|
|
@@ -5,11 +5,14 @@ import com.malk.lanyun.service.DingTalkService;
|
|
|
import com.malk.server.dingtalk.DDConf;
|
|
|
import com.malk.server.dingtalk.DDR;
|
|
|
import com.malk.service.dingtalk.DDClient;
|
|
|
+import com.malk.service.dingtalk.DDClient_Contacts;
|
|
|
import com.malk.service.dingtalk.DDClient_Personnel;
|
|
|
import com.malk.service.dingtalk.DDClient_Workflow;
|
|
|
import com.malk.utils.UtilMap;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
@@ -27,16 +30,23 @@ public class DingTalkServiceImpl implements DingTalkService {
|
|
|
|
|
|
private final DDClient_Workflow ddClientWorkflow;
|
|
|
|
|
|
+ private final DDClient_Contacts ddClientContacts;
|
|
|
+
|
|
|
private final DDClient_Personnel ddClientPersonnel;
|
|
|
|
|
|
private final DDConf ddConf;
|
|
|
|
|
|
+ private final JdbcTemplate jdbcTemplate;
|
|
|
+
|
|
|
public DingTalkServiceImpl(DDClient ddClient, DDClient_Workflow ddClientWorkflow,
|
|
|
- DDClient_Personnel ddClientPersonnel, DDConf ddConf) {
|
|
|
+ DDClient_Contacts ddClientContacts, DDClient_Personnel ddClientPersonnel, DDConf ddConf,
|
|
|
+ JdbcTemplate jdbcTemplate) {
|
|
|
this.ddClient = ddClient;
|
|
|
this.ddClientWorkflow = ddClientWorkflow;
|
|
|
+ this.ddClientContacts = ddClientContacts;
|
|
|
this.ddClientPersonnel = ddClientPersonnel;
|
|
|
this.ddConf = ddConf;
|
|
|
+ this.jdbcTemplate = jdbcTemplate;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -61,19 +71,57 @@ public class DingTalkServiceImpl implements DingTalkService {
|
|
|
*/
|
|
|
@Override
|
|
|
public int syncApprovalFormToRoster(String processInstanceId) {
|
|
|
- if (isBlank(processInstanceId)) {
|
|
|
- throw new IllegalArgumentException("processInstanceId不能为空");
|
|
|
- }
|
|
|
- // 审批应用凭证: 用于查询审批实例
|
|
|
- String approvalAccessToken = this.ddClient.getAccessToken(this.ddConf.getApprovalAppKey(), this.ddConf.getApprovalAppSecret());
|
|
|
- Map processData = this.ddClientWorkflow.getProcessInstanceId(approvalAccessToken, processInstanceId);
|
|
|
- if (processData == null || processData.isEmpty()) {
|
|
|
- throw new IllegalStateException("未查询到审批实例, processInstanceId=" + processInstanceId);
|
|
|
- }
|
|
|
+ Map processData = getApprovalProcessData(processInstanceId);
|
|
|
String userId = stringValue(processData.get("originatorUserId"));
|
|
|
if (isBlank(userId)) {
|
|
|
throw new IllegalStateException("审批实例缺少发起人, processInstanceId=" + processInstanceId);
|
|
|
}
|
|
|
+ return updateEmployeeRoster(processInstanceId, userId, processData);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String findProcessInstanceIdByUserId(String userId) {
|
|
|
+ if (isBlank(userId)) {
|
|
|
+ throw new IllegalArgumentException("userId不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String contactsAccessToken = this.ddClient.getAccessToken(
|
|
|
+ this.ddConf.getAppKey(), this.ddConf.getAppSecret());
|
|
|
+ Map userInfo = this.ddClientContacts.getUserInfoById(contactsAccessToken, userId);
|
|
|
+ if (userInfo == null || userInfo.isEmpty()) {
|
|
|
+ throw new IllegalStateException("未查询到通讯录用户, userId=" + userId);
|
|
|
+ }
|
|
|
+ String phone = normalizePhone(firstNotBlank(
|
|
|
+ stringValue(userInfo.get("mobile")), stringValue(userInfo.get("telephone"))));
|
|
|
+ if (isBlank(phone)) {
|
|
|
+ throw new IllegalStateException("通讯录用户缺少手机号, userId=" + userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map<String, Object>> rows = this.jdbcTemplate.queryForList(
|
|
|
+ "SELECT processInstanceId AS process_instance_id "
|
|
|
+ + "FROM add_user_lanyun WHERE phone = ? ORDER BY id DESC LIMIT 1",
|
|
|
+ phone);
|
|
|
+ if (rows.isEmpty()) {
|
|
|
+ log.info("新增通讯录用户没有匹配的审批记录, userId={}", userId);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String processInstanceId = stringValue(rows.get(0).get("process_instance_id"));
|
|
|
+ if (isBlank(processInstanceId)) {
|
|
|
+ throw new IllegalStateException("用户审批记录缺少processInstanceId, userId=" + userId);
|
|
|
+ }
|
|
|
+ return processInstanceId;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int upsertApprovalUser(String processInstanceId, String userId) {
|
|
|
+ if (isBlank(userId)) {
|
|
|
+ throw new IllegalArgumentException("userId不能为空");
|
|
|
+ }
|
|
|
+ Map processData = getApprovalProcessData(processInstanceId);
|
|
|
+ return updateEmployeeRoster(processInstanceId, userId, processData);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int updateEmployeeRoster(String processInstanceId, String userId, Map processData) {
|
|
|
// 花名册应用凭证: 用于读写智能人事花名册
|
|
|
String personnelAccessToken = this.ddClient.getAccessToken(this.ddConf.getAppKey(), this.ddConf.getAppSecret());
|
|
|
List<Map> formComponentValues = asMapList(processData.get("formComponentValues"));
|
|
|
@@ -111,6 +159,92 @@ public class DingTalkServiceImpl implements DingTalkService {
|
|
|
return matchedCount;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 审批通过后,将审批单中的姓名和手机号写入 add_user_lanyun。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public int upsertApprovalUser(String processInstanceId) {
|
|
|
+ Map processData = getApprovalProcessData(processInstanceId);
|
|
|
+
|
|
|
+ List<Map> formComponentValues = asMapList(processData.get("formComponentValues"));
|
|
|
+ String name = requiredFormValue(formComponentValues, "姓名", "人员姓名", "name", "入职员工姓名");
|
|
|
+ String phone = requiredFormValue(formComponentValues, "手机号", "手机号码", "联系电话", "phone", "mobile")
|
|
|
+ .replaceAll("\\s+", "");
|
|
|
+
|
|
|
+ int updatedCount = this.jdbcTemplate.update(
|
|
|
+ "UPDATE add_user_lanyun SET name = ?, processInstanceId = ? WHERE phone = ?",
|
|
|
+ name, processInstanceId, phone);
|
|
|
+ if (updatedCount > 0) {
|
|
|
+ log.info("审批用户已更新, processInstanceId={}, affectedRows={}", processInstanceId, updatedCount);
|
|
|
+ return updatedCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ int insertedCount = this.jdbcTemplate.update(
|
|
|
+ "INSERT INTO add_user_lanyun (name, phone, processInstanceId) VALUES (?, ?, ?)",
|
|
|
+ name, phone, processInstanceId);
|
|
|
+ log.info("审批用户已新增, processInstanceId={}, affectedRows={}", processInstanceId, insertedCount);
|
|
|
+ return insertedCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map getApprovalProcessData(String processInstanceId) {
|
|
|
+ if (isBlank(processInstanceId)) {
|
|
|
+ throw new IllegalArgumentException("processInstanceId不能为空");
|
|
|
+ }
|
|
|
+ String accessToken = this.ddClient.getAccessToken(
|
|
|
+ this.ddConf.getAppKey(), this.ddConf.getAppSecret());
|
|
|
+ Map processData = this.ddClientWorkflow.getProcessInstanceId(accessToken, processInstanceId);
|
|
|
+ if (processData == null || processData.isEmpty()) {
|
|
|
+ throw new IllegalStateException("未查询到审批实例, processInstanceId=" + processInstanceId);
|
|
|
+ }
|
|
|
+ return processData;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String normalizePhone(String phone) {
|
|
|
+ return isBlank(phone) ? null : phone.replaceAll("\\s+", "");
|
|
|
+ }
|
|
|
+
|
|
|
+ private String firstNotBlank(String... values) {
|
|
|
+ for (String value : values) {
|
|
|
+ if (!isBlank(value)) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String requiredFormValue(List<Map> formComponentValues, String... fieldNames) {
|
|
|
+ for (Map component : safeList(formComponentValues)) {
|
|
|
+ if (!matchesField(component, fieldNames)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String value = stringValue(component.get("value"));
|
|
|
+ if (!isBlank(value)) {
|
|
|
+ return value.trim();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new IllegalStateException("审批单缺少必填字段: " + String.join("/", fieldNames));
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean matchesField(Map component, String... fieldNames) {
|
|
|
+ String[] componentNames = {
|
|
|
+ stringValue(component.get("name")),
|
|
|
+ stringValue(component.get("label")),
|
|
|
+ stringValue(component.get("bizAlias"))
|
|
|
+ };
|
|
|
+ for (String componentName : componentNames) {
|
|
|
+ if (isBlank(componentName)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (String fieldName : fieldNames) {
|
|
|
+ if (fieldName.equalsIgnoreCase(componentName.trim())) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 花名册字段索引: 字段名称 -> 分组ID + 字段编码
|
|
|
*/
|