|
@@ -0,0 +1,282 @@
|
|
|
+package nckd.jimin.jyyy.hr.haos.staff.plugin.task;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import kd.bos.dataentity.entity.DynamicObject;
|
|
|
+import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
|
+import kd.bos.exception.KDException;
|
|
|
+import kd.bos.logging.Log;
|
|
|
+import kd.bos.logging.LogFactory;
|
|
|
+import kd.bos.orm.query.QCP;
|
|
|
+import kd.bos.orm.query.QFilter;
|
|
|
+import kd.bos.servicehelper.BusinessDataServiceHelper;
|
|
|
+import kd.bos.servicehelper.QueryServiceHelper;
|
|
|
+import kd.bos.servicehelper.operation.SaveServiceHelper;
|
|
|
+import kd.bos.util.HttpClientUtils;
|
|
|
+import kd.bos.workflow.exception.WFErrorCode;
|
|
|
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+public class SyncUtil {
|
|
|
+ private static Log logger = LogFactory.getLog(SyncUtil.class);
|
|
|
+ private static String KEY_ENTITY_LOG = "nckd_syncmdmlog";
|
|
|
+ public static String v_success = "A";
|
|
|
+ public static String v_partsuccess = "B";
|
|
|
+ public static String v_error = "C";
|
|
|
+ public static String SyncOrg = "组织同步";
|
|
|
+ public static String SyncPerson = "人员同步";
|
|
|
+ public static String SyncPosition = "岗位同步";
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取调用MDM的地址,取nckd_commonparams中编码=MDM的参数
|
|
|
+ * @param type
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String getUrl(String type) {
|
|
|
+ QFilter filter = new QFilter("number", QCP.equals, "MDM");
|
|
|
+ filter.and("nckd_entryentity.nckd_key",QCP.equals, type);
|
|
|
+ DynamicObject bill = QueryServiceHelper.queryOne("nckd_commonparams", "nckd_entryentity.nckd_value", new QFilter[]{filter});
|
|
|
+ logger.info("-------- 获取MDM url:" + bill.getString("nckd_entryentity.nckd_value") + " -------- ");
|
|
|
+ return bill.getString("nckd_entryentity.nckd_value");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化组织Id和长编码的关系
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Map<Long, DynamicObject> initOrgInfo() {
|
|
|
+ String selectFields = "id,structure.vieworg.id,structure.longnumber,structure.fullname,createtime";
|
|
|
+ QFilter filter = new QFilter("structure.view.id",QCP.equals,1L);
|
|
|
+ DynamicObjectCollection orgs = QueryServiceHelper.query("bos_org", selectFields, new QFilter[]{filter});
|
|
|
+
|
|
|
+ Map<Long, DynamicObject> orgMap = (Map)orgs.stream().collect(Collectors.toMap((org) -> {
|
|
|
+ return org.getLong("id");
|
|
|
+ }, (org) -> {
|
|
|
+ return org;
|
|
|
+ }, (key1, key2) -> {
|
|
|
+ return key2;
|
|
|
+ }));
|
|
|
+
|
|
|
+ return orgMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Map<Long, DynamicObject> initOrgInfo(Map orgMap) {
|
|
|
+ String selectFields = "id,structure.vieworg.id,structure.longnumber,structure.fullname,createtime";
|
|
|
+ QFilter filter = new QFilter("structure.view.id",QCP.equals,1L);
|
|
|
+ filter.and("id",QCP.in,orgMap.keySet());
|
|
|
+ DynamicObjectCollection orgs = QueryServiceHelper.query("bos_org", selectFields, new QFilter[]{filter});
|
|
|
+
|
|
|
+ Map<Long, DynamicObject> orgDyxMap = (Map)orgs.stream().collect(Collectors.toMap((org) -> {
|
|
|
+ return org.getLong("id");
|
|
|
+ }, (org) -> {
|
|
|
+ return org;
|
|
|
+ }, (key1, key2) -> {
|
|
|
+ return key2;
|
|
|
+ }));
|
|
|
+
|
|
|
+ return orgDyxMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 岗位树形结构,为了解决level字段问题
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Map<Long, Integer> initPositionTree() {
|
|
|
+ String selectProperties = "id,parent.id,name,iscurrentversion";
|
|
|
+ QFilter filter = new QFilter("iscurrentversion", QCP.equals, "1");
|
|
|
+ DynamicObjectCollection posDyArr = new HRBaseServiceHelper("homs_positionhis").queryOriginalCollection(selectProperties, new QFilter[]{filter});
|
|
|
+ List<PositionTree> list = new ArrayList<PositionTree>();
|
|
|
+ for (DynamicObject pos : posDyArr) {
|
|
|
+ PositionTree pTree = new PositionTree(pos.getLong("id"), pos.getString("name"), pos.getLong("parent.id"));
|
|
|
+ list.add(pTree);
|
|
|
+ }
|
|
|
+ //构造树形结构,带level
|
|
|
+ List<PositionTree> tree = buildTree(list);
|
|
|
+ //处理实现结构,返回一个id-level的Map
|
|
|
+ Map<Long, Integer> levelMap = convertToIdLevelMap(tree);
|
|
|
+ return levelMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Map<Long, Integer> convertToIdLevelMap(List<PositionTree> roots) {
|
|
|
+ Map<Long, Integer> idLevelMap = new HashMap<>();
|
|
|
+ for(PositionTree root : roots) {
|
|
|
+ traverseTree(root, idLevelMap);
|
|
|
+ }
|
|
|
+ return idLevelMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void traverseTree(PositionTree node, Map<Long, Integer> map) {
|
|
|
+ map.put(node.getId(), node.getLevel());
|
|
|
+ for (PositionTree child : node.getChildren()) {
|
|
|
+ traverseTree(child, map); // 递归处理子节点:ml-citation{ref="1,3" data="citationList"}
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 递归打印树
|
|
|
+ private static void printTree(PositionTree node, int indent) {
|
|
|
+ String spaces = String.join("", Collections.nCopies(indent, " "));
|
|
|
+ System.out.println(spaces + "└─ " + node.getLabel());
|
|
|
+ for (PositionTree child : node.getChildren()) {
|
|
|
+ printTree(child, indent + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建完整树形结构
|
|
|
+ * @param nodes 所有平铺节点
|
|
|
+ * @return 根节点列表(支持多根)
|
|
|
+ */
|
|
|
+ public static List<PositionTree> buildTree(List<PositionTree> nodes) {
|
|
|
+ // 1. 创建快速查找的哈希表
|
|
|
+ Map<Long, PositionTree> nodeMap = nodes.stream()
|
|
|
+ .collect(Collectors.toMap(PositionTree::getId, node -> node));
|
|
|
+
|
|
|
+ // 2. 构建父子关系
|
|
|
+ List<PositionTree> roots = new ArrayList<>();
|
|
|
+ for (PositionTree node : nodes) {
|
|
|
+ Long parentId = node.getParentId();
|
|
|
+ if (parentId == null || parentId == 0L) {
|
|
|
+ roots.add(node); // 根节点
|
|
|
+ } else {
|
|
|
+ PositionTree parent = nodeMap.get(parentId);
|
|
|
+ if (parent != null) {
|
|
|
+ parent.getChildren().add(node);
|
|
|
+ } else {
|
|
|
+ // 处理孤儿节点(可选)
|
|
|
+ roots.add(node); // 将无父节点的视为根节点
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 计算层级(可选扩展)
|
|
|
+ calculateLevels(roots, 0);
|
|
|
+
|
|
|
+ return roots;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 递归计算层级深度 */
|
|
|
+ private static void calculateLevels(List<PositionTree> nodes, int level) {
|
|
|
+ for (PositionTree node : nodes) {
|
|
|
+ node.setLevel(level);
|
|
|
+ calculateLevels(node.getChildren(), level + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * JSONArray排序,按照级次排序,避免下级数据新增的时候上级还没有
|
|
|
+ * @param arr
|
|
|
+ * @param fieldName
|
|
|
+ */
|
|
|
+ public static void setJSONArraySorted(JSONArray arr, String fieldName) {
|
|
|
+ arr.sort((a, b) -> {
|
|
|
+ JSONObject objA = (JSONObject) a;
|
|
|
+ JSONObject objB = (JSONObject) b;
|
|
|
+ return objA.getIntValue(fieldName) - objB.getIntValue(fieldName);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param url
|
|
|
+ * @param bodyData
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static JSONObject doPostByHttpClient(String url, JSONObject bodyData) {
|
|
|
+ try {
|
|
|
+ Map<String, String> headers = new HashMap();
|
|
|
+ headers.put("Content-Type", "application/json");
|
|
|
+ headers.put("Accept", "*/*");
|
|
|
+ logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
|
|
|
+ System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
|
|
|
+
|
|
|
+ String responseEntify = HttpClientUtils.postjson(url, headers, bodyData.toJSONString());
|
|
|
+
|
|
|
+ logger.info(responseEntify);
|
|
|
+ JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
|
|
|
+ return result;
|
|
|
+ } catch (IOException var5) {
|
|
|
+ throw new KDException(var5, WFErrorCode.httpRequestException(), new Object[]{var5.getMessage()});
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理MDM返回结果 A-成功 B-部分成功 C-失败
|
|
|
+ * @param response
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String dealResponseStatus (JSONObject response) {
|
|
|
+ String status = "";
|
|
|
+ int successCount = 0;
|
|
|
+ int errorCount = 0;
|
|
|
+ JSONArray responseData = response.getJSONArray("responseData");
|
|
|
+ //根据明细数据status分组
|
|
|
+ Map<String, JSONArray> responseDataMap = responseData.stream().map(obj -> (JSONObject) obj)
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ json -> json.getString("status"),
|
|
|
+ () -> new HashMap<>(),
|
|
|
+ Collectors.mapping(JSONObject::toJSON, Collectors.toCollection(JSONArray::new))
|
|
|
+ ));
|
|
|
+ JSONArray sucArr = responseDataMap.get("S");
|
|
|
+ JSONArray errArr = responseDataMap.get("E");
|
|
|
+ if(sucArr != null)
|
|
|
+ successCount = sucArr.size();
|
|
|
+ if(errArr != null)
|
|
|
+ errorCount = errArr.size();
|
|
|
+
|
|
|
+ if(errorCount > 0 && successCount > 0) {
|
|
|
+ status = "B";
|
|
|
+ }
|
|
|
+ else if(successCount == 0 && errorCount > 0) {
|
|
|
+ status = "C";
|
|
|
+ }
|
|
|
+ else if(successCount > 0 && errorCount == 0) {
|
|
|
+ status = "A";
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建同步日志
|
|
|
+ * @param status 同步状态 A-成功 B-部分成功 C-失败
|
|
|
+ * @param startTime 变动开始时间
|
|
|
+ * @param endTime 变动结束时间
|
|
|
+ * @param request 请求报文
|
|
|
+ * @param response 返回报文
|
|
|
+ * @param syncType 同步类型
|
|
|
+ */
|
|
|
+ public static void createLog (String status, String startTime, String endTime, String request, String response, String syncType) {
|
|
|
+ DynamicObject dynamicObject = BusinessDataServiceHelper.newDynamicObject(KEY_ENTITY_LOG);
|
|
|
+ String uuid = UUID.randomUUID().toString().replace("-", "");
|
|
|
+ dynamicObject.set("enable", "1");
|
|
|
+ dynamicObject.set("status", "C");
|
|
|
+ dynamicObject.set("number", uuid.substring(0,29));
|
|
|
+ dynamicObject.set("nckd_starttime", startTime);
|
|
|
+ dynamicObject.set("nckd_endtime", endTime);
|
|
|
+ dynamicObject.set("nckd_status", status);
|
|
|
+ dynamicObject.set("nckd_synctype", syncType);
|
|
|
+ if (request.length() < 200) {
|
|
|
+ dynamicObject.set("nckd_request", request);
|
|
|
+ } else {
|
|
|
+ dynamicObject.set("nckd_request", request.substring(0, 200) + "...");
|
|
|
+ }
|
|
|
+ dynamicObject.set("nckd_request_tag", request);
|
|
|
+
|
|
|
+ if (response.length() < 200) {
|
|
|
+ dynamicObject.set("nckd_response", response);
|
|
|
+ } else {
|
|
|
+ dynamicObject.set("nckd_response", response.substring(0, 200) + "...");
|
|
|
+ }
|
|
|
+ dynamicObject.set("nckd_response_tag", response);
|
|
|
+ SaveServiceHelper.save(new DynamicObject[]{dynamicObject});
|
|
|
+ logger.info("-------- 保存日志 --------");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|