|
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import com.malk.minglei.config.YidaApplicationsProperties;
|
|
import com.malk.minglei.config.YidaApplicationsProperties;
|
|
|
import com.malk.minglei.dto.MingleiDocumentQueryRequest;
|
|
import com.malk.minglei.dto.MingleiDocumentQueryRequest;
|
|
|
|
|
+import com.malk.minglei.service.employee.EmployeeRosterService;
|
|
|
import com.malk.minglei.service.yida.MingleiDocumentService;
|
|
import com.malk.minglei.service.yida.MingleiDocumentService;
|
|
|
import com.malk.server.aliwork.YDConf;
|
|
import com.malk.server.aliwork.YDConf;
|
|
|
import com.malk.server.aliwork.YDParam;
|
|
import com.malk.server.aliwork.YDParam;
|
|
@@ -12,6 +13,8 @@ import com.malk.server.dingtalk.DDConf;
|
|
|
import com.malk.service.aliwork.YDClient;
|
|
import com.malk.service.aliwork.YDClient;
|
|
|
import com.malk.service.dingtalk.DDClient;
|
|
import com.malk.service.dingtalk.DDClient;
|
|
|
import com.malk.service.dingtalk.DDClient_Contacts;
|
|
import com.malk.service.dingtalk.DDClient_Contacts;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
@@ -29,6 +32,7 @@ import java.util.Set;
|
|
|
@Service
|
|
@Service
|
|
|
public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
|
|
|
|
|
|
|
+ private static final Logger LOGGER = LoggerFactory.getLogger(MingleiDocumentServiceImpl.class);
|
|
|
private static final String MINGLEI_DOCUMENT_FORM_UUID = "FORM-8F527F696C5B4AF7AB7A53979527FBA23USO";
|
|
private static final String MINGLEI_DOCUMENT_FORM_UUID = "FORM-8F527F696C5B4AF7AB7A53979527FBA23USO";
|
|
|
private static final String DEPARTMENT_ID_FIELD_ID = "textField_msztwhs2";
|
|
private static final String DEPARTMENT_ID_FIELD_ID = "textField_msztwhs2";
|
|
|
private static final String DEPARTMENT_NAME_FIELD_ID = "textField_mszr6tuz";
|
|
private static final String DEPARTMENT_NAME_FIELD_ID = "textField_mszr6tuz";
|
|
@@ -45,7 +49,8 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
FOURTH_LEVEL_DEPARTMENT_MANAGER_FIELD_ID,
|
|
FOURTH_LEVEL_DEPARTMENT_MANAGER_FIELD_ID,
|
|
|
DEPARTMENT_LEADER_FIELD_ID
|
|
DEPARTMENT_LEADER_FIELD_ID
|
|
|
};
|
|
};
|
|
|
- private static final int PRECISE_QUERY_PAGE_SIZE = 100;
|
|
|
|
|
|
|
+ private static final int APPROVAL_MATRIX_QUERY_PAGE_SIZE = 1;
|
|
|
|
|
+ private static final int APPLICANT_CONFIGURATION_QUERY_PAGE_SIZE = 100;
|
|
|
|
|
|
|
|
private final YDClient yidaClient;
|
|
private final YDClient yidaClient;
|
|
|
private final DDClient dingTalkClient;
|
|
private final DDClient dingTalkClient;
|
|
@@ -53,6 +58,7 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
private final DDConf dingTalkConfiguration;
|
|
private final DDConf dingTalkConfiguration;
|
|
|
private final YidaApplicationsProperties.ApplicationCredentials masterDataConfiguration;
|
|
private final YidaApplicationsProperties.ApplicationCredentials masterDataConfiguration;
|
|
|
private final ObjectMapper objectMapper;
|
|
private final ObjectMapper objectMapper;
|
|
|
|
|
+ private final EmployeeRosterService employeeRosterService;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 创建明磊主数据表单查询服务。
|
|
* 创建明磊主数据表单查询服务。
|
|
@@ -63,19 +69,22 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
* @param dingTalkConfiguration 钉钉应用配置
|
|
* @param dingTalkConfiguration 钉钉应用配置
|
|
|
* @param applications 宜搭应用配置
|
|
* @param applications 宜搭应用配置
|
|
|
* @param objectMapper JSON 序列化组件
|
|
* @param objectMapper JSON 序列化组件
|
|
|
|
|
+ * @param employeeRosterService 员工花名册服务
|
|
|
*/
|
|
*/
|
|
|
public MingleiDocumentServiceImpl(@Qualifier("masterDataYidaClient") YDClient yidaClient,
|
|
public MingleiDocumentServiceImpl(@Qualifier("masterDataYidaClient") YDClient yidaClient,
|
|
|
DDClient dingTalkClient,
|
|
DDClient dingTalkClient,
|
|
|
DDClient_Contacts dingTalkContactsClient,
|
|
DDClient_Contacts dingTalkContactsClient,
|
|
|
DDConf dingTalkConfiguration,
|
|
DDConf dingTalkConfiguration,
|
|
|
YidaApplicationsProperties applications,
|
|
YidaApplicationsProperties applications,
|
|
|
- ObjectMapper objectMapper) {
|
|
|
|
|
|
|
+ ObjectMapper objectMapper,
|
|
|
|
|
+ EmployeeRosterService employeeRosterService) {
|
|
|
this.yidaClient = yidaClient;
|
|
this.yidaClient = yidaClient;
|
|
|
this.dingTalkClient = dingTalkClient;
|
|
this.dingTalkClient = dingTalkClient;
|
|
|
this.dingTalkContactsClient = dingTalkContactsClient;
|
|
this.dingTalkContactsClient = dingTalkContactsClient;
|
|
|
this.dingTalkConfiguration = dingTalkConfiguration;
|
|
this.dingTalkConfiguration = dingTalkConfiguration;
|
|
|
this.masterDataConfiguration = applications.getMasterData();
|
|
this.masterDataConfiguration = applications.getMasterData();
|
|
|
this.objectMapper = objectMapper;
|
|
this.objectMapper = objectMapper;
|
|
|
|
|
+ this.employeeRosterService = employeeRosterService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -101,23 +110,40 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
if (request == null) {
|
|
if (request == null) {
|
|
|
throw new IllegalArgumentException("Query request must not be null");
|
|
throw new IllegalArgumentException("Query request must not be null");
|
|
|
}
|
|
}
|
|
|
|
|
+ long startedAt = System.nanoTime();
|
|
|
|
|
+ String queryType = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ String departmentId = trimToNull(request.getDeptId());
|
|
|
|
|
+ if (departmentId != null) {
|
|
|
|
|
+ queryType = "dept_id";
|
|
|
|
|
+ return queryApprovalMatrix(queryType, DEPARTMENT_ID_FIELD_ID, departmentId);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- String departmentId = trimToNull(request.getDeptId());
|
|
|
|
|
- if (departmentId != null) {
|
|
|
|
|
- return extractDepartmentManagers(executeQuery(DEPARTMENT_ID_FIELD_ID, departmentId, 1, PRECISE_QUERY_PAGE_SIZE));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ String userId = trimToNull(request.getUserId());
|
|
|
|
|
+ if (userId != null) {
|
|
|
|
|
+ queryType = "user_id";
|
|
|
|
|
+ long userDepartmentStartedAt = System.nanoTime();
|
|
|
|
|
+ String resolvedDepartmentId;
|
|
|
|
|
+ try {
|
|
|
|
|
+ resolvedDepartmentId = resolveDepartmentId(userId);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ LOGGER.info("Approval matrix query stage=RESOLVE_USER_DEPARTMENT durationMs={}",
|
|
|
|
|
+ elapsedMillis(userDepartmentStartedAt));
|
|
|
|
|
+ }
|
|
|
|
|
+ return queryApprovalMatrix(queryType, DEPARTMENT_ID_FIELD_ID, resolvedDepartmentId);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- String userId = trimToNull(request.getUserId());
|
|
|
|
|
- if (userId != null) {
|
|
|
|
|
- return extractDepartmentManagers(executeQuery(DEPARTMENT_ID_FIELD_ID, resolveDepartmentId(userId), 1, PRECISE_QUERY_PAGE_SIZE));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ String departmentName = trimToNull(request.getDeptName());
|
|
|
|
|
+ if (departmentName != null) {
|
|
|
|
|
+ queryType = "dept_name";
|
|
|
|
|
+ return queryApprovalMatrix(queryType, DEPARTMENT_NAME_FIELD_ID, departmentName);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- String departmentName = trimToNull(request.getDeptName());
|
|
|
|
|
- if (departmentName != null) {
|
|
|
|
|
- return extractDepartmentManagers(executeQuery(DEPARTMENT_NAME_FIELD_ID, departmentName, 1, PRECISE_QUERY_PAGE_SIZE));
|
|
|
|
|
|
|
+ throw new IllegalArgumentException("One of dept_id, user_id or dept_name must be provided");
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ LOGGER.info("Approval matrix query completed queryType={} durationMs={}", queryType,
|
|
|
|
|
+ elapsedMillis(startedAt));
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- throw new IllegalArgumentException("One of dept_id, user_id or dept_name must be provided");
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -133,7 +159,7 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
throw new IllegalArgumentException("departmentId must not be blank");
|
|
throw new IllegalArgumentException("departmentId must not be blank");
|
|
|
}
|
|
}
|
|
|
return extractDepartmentManagers(executeQuery(DEPARTMENT_ID_FIELD_ID, requestedDepartmentId,
|
|
return extractDepartmentManagers(executeQuery(DEPARTMENT_ID_FIELD_ID, requestedDepartmentId,
|
|
|
- 1, PRECISE_QUERY_PAGE_SIZE));
|
|
|
|
|
|
|
+ 1, APPROVAL_MATRIX_QUERY_PAGE_SIZE));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -147,7 +173,8 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
String requestedUserId = trimToNull(userId);
|
|
String requestedUserId = trimToNull(userId);
|
|
|
require(requestedUserId, "userId must not be blank");
|
|
require(requestedUserId, "userId must not be blank");
|
|
|
String departmentId = resolveDepartmentId(requestedUserId);
|
|
String departmentId = resolveDepartmentId(requestedUserId);
|
|
|
- Map<String, Object> queryResult = executeQuery(DEPARTMENT_ID_FIELD_ID, departmentId, 1, PRECISE_QUERY_PAGE_SIZE);
|
|
|
|
|
|
|
+ Map<String, Object> queryResult = executeQuery(DEPARTMENT_ID_FIELD_ID, departmentId, 1,
|
|
|
|
|
+ APPLICANT_CONFIGURATION_QUERY_PAGE_SIZE);
|
|
|
Map formData = firstFormData(queryResult.get("records"));
|
|
Map formData = firstFormData(queryResult.get("records"));
|
|
|
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
|
|
result.put("departmentId", departmentId);
|
|
result.put("departmentId", departmentId);
|
|
@@ -253,6 +280,26 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询审批矩阵时每个部门只应有一条有效配置,因此仅请求首条记录,避免传输和解析无关表单数据。
|
|
|
|
|
+ */
|
|
|
|
|
+ private Map<String, Object> queryApprovalMatrix(String queryType, String fieldId, String fieldValue) {
|
|
|
|
|
+ long startedAt = System.nanoTime();
|
|
|
|
|
+ Object totalCount = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ Map<String, Object> queryResult = executeQuery(fieldId, fieldValue, 1, APPROVAL_MATRIX_QUERY_PAGE_SIZE);
|
|
|
|
|
+ totalCount = queryResult.get("totalCount");
|
|
|
|
|
+ return extractDepartmentManagers(queryResult);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ LOGGER.info("Approval matrix query stage=YIDA_MATRIX_QUERY queryType={} durationMs={} totalCount={}",
|
|
|
|
|
+ queryType, elapsedMillis(startedAt), totalCount);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private long elapsedMillis(long startedAt) {
|
|
|
|
|
+ return (System.nanoTime() - startedAt) / 1_000_000L;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 从精准查询命中的首条单据提取五个主管字段对应的用户 ID,并直接返回到顶层。
|
|
* 从精准查询命中的首条单据提取五个主管字段对应的用户 ID,并直接返回到顶层。
|
|
|
*
|
|
*
|
|
@@ -336,28 +383,15 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 调用钉钉通讯录接口读取员工所属部门,并取返回列表中的首个部门编号作为查询条件。
|
|
|
|
|
|
|
+ * 从已同步的本地员工花名册读取员工部门编号,避免审批矩阵查询依赖钉钉用户详情接口。
|
|
|
*
|
|
*
|
|
|
* @param userId 钉钉用户编号
|
|
* @param userId 钉钉用户编号
|
|
|
* @return 员工所属的部门编号
|
|
* @return 员工所属的部门编号
|
|
|
*/
|
|
*/
|
|
|
private String resolveDepartmentId(String userId) {
|
|
private String resolveDepartmentId(String userId) {
|
|
|
- Map userInfo = dingTalkContactsClient.getUserInfoById(dingTalkClient.getAccessToken(), userId);
|
|
|
|
|
- if (userInfo == null) {
|
|
|
|
|
- throw new IllegalArgumentException("No DingTalk user information was found for user_id");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- String mainDepartmentId = toStringValue(userInfo.get("main_dept_id"));
|
|
|
|
|
- if (mainDepartmentId != null) {
|
|
|
|
|
- return mainDepartmentId;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- String departmentId = firstDepartmentId(userInfo.get("department"));
|
|
|
|
|
|
|
+ String departmentId = employeeRosterService.findDepartmentIdByUserId(userId);
|
|
|
if (departmentId == null) {
|
|
if (departmentId == null) {
|
|
|
- departmentId = firstDepartmentId(userInfo.get("dept_id_list"));
|
|
|
|
|
- }
|
|
|
|
|
- if (departmentId == null) {
|
|
|
|
|
- throw new IllegalArgumentException("No department was found for user_id");
|
|
|
|
|
|
|
+ throw new IllegalArgumentException("No synchronized employee roster department was found for user_id");
|
|
|
}
|
|
}
|
|
|
return departmentId;
|
|
return departmentId;
|
|
|
}
|
|
}
|
|
@@ -383,29 +417,6 @@ public class MingleiDocumentServiceImpl implements MingleiDocumentService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private String firstDepartmentId(Object departmentIds) {
|
|
|
|
|
- if (departmentIds instanceof Iterable) {
|
|
|
|
|
- for (Object departmentId : (Iterable<?>) departmentIds) {
|
|
|
|
|
- String value = toStringValue(departmentId);
|
|
|
|
|
- if (value != null) {
|
|
|
|
|
- return value;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- if (departmentIds != null && departmentIds.getClass().isArray()) {
|
|
|
|
|
- Object[] values = (Object[]) departmentIds;
|
|
|
|
|
- for (Object departmentId : values) {
|
|
|
|
|
- String value = toStringValue(departmentId);
|
|
|
|
|
- if (value != null) {
|
|
|
|
|
- return value;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- return toStringValue(departmentIds);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private String toStringValue(Object value) {
|
|
private String toStringValue(Object value) {
|
|
|
return value == null ? null : trimToNull(String.valueOf(value));
|
|
return value == null ? null : trimToNull(String.valueOf(value));
|
|
|
}
|
|
}
|