pruple_boy 1 年之前
父節點
當前提交
c6c78d86be

File diff suppressed because it is too large
+ 43 - 49
mjava-aiwei/src/main/java/com/malk/aiwei/controller/TBxYDController.java


+ 2 - 66
mjava-aiwei/src/main/java/com/malk/aiwei/delegate/TBDelegate.java

@@ -1,27 +1,15 @@
 package com.malk.aiwei.delegate;
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.malk.aiwei.service.AWClint;
 import com.malk.delegate.TBEvent;
-import com.malk.server.dingtalk.DDConf;
-import com.malk.server.teambition.TBConf;
-import com.malk.service.teambition.TBClient;
-import com.malk.utils.UtilMap;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Primary;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
 /**
  * OA审批事件 [主项目也有实现, 添加 @Primary 优先注入主项目实现]
  * -
@@ -33,71 +21,19 @@ import java.util.stream.Collectors;
 @Primary
 public class TBDelegate implements TBEvent {
 
-
-    @Autowired
-    private TBClient tbClient;
-
     @Autowired
     private AWClint awClint;
 
-    @Autowired
-    private DDConf ddConf;
-
     @Async
     @Override
     @SneakyThrows
     public void callBackTask(JSONObject eventJson) {
         String eventName = eventJson.getString("event");
         log.info("callBackTask, {}, {}", eventName, eventJson);
-        // todo 查询工作流接口
-        if ("v3.task.taskflowstatus.update".equals(eventName)) {
 
+        if ("v3.task.taskflowstatus.update".equals(eventName)) {
             JSONObject data = eventJson.getJSONObject("data");
-            List<String> workDones = Arrays.asList("659679ec3bf0fb46b4b68ca2", "65964fe63bf0fb46b4b6264d", "65964fe63bf0fb46b4b6264f"); // "65937802de54cc9e2351121c"; // 已完成, 触发checklist
-            String approve = "65967ad70e25b16b2e91e568"; // "65937802de54cc9e23511219"; // 提交评审, 触发交付物审批
-            List<String> allState = new ArrayList<>();
-            allState.addAll(workDones);
-            allState.add(approve);
-            if (!allState.contains(data.getString("tfsId"))) {
-                return;
-            }
-            List<Map> rTask = tbClient.queryTaskDetail(data.getString("taskId"), null, null);
-            List<Map> customfields = UtilMap.getList(rTask.get(0), "customfields");
-            String taskCode = "658d21e84aa556a15b887402"; // "659a67b83207833e1e2f744e"; // 任务编码字段ID
-            String tCode = TBConf.getTaskFieldValue_First(customfields, taskCode);
-            // 过滤编码为空任务
-            if (StringUtils.isBlank(tCode)) {
-                return;
-            }
-            // 匹配发起人, 新版本id映射表解析
-            Map<String, String> extra = (Map) tbClient.idMapQuery(data.getString("creatorId"), "dingTalk-user", ddConf.getCorpId()).get(0).get("extra");
-            String userId = extra.get("userId");
-            if (workDones.contains(data.getString("tfsId"))) {
-                String result = awClint.check(tCode, data.getString("projectId"), data.getString("taskId"), data.getString("creatorId"), userId);
-                if (StringUtils.isBlank(result)) {
-                    return;
-                }
-                // 回写审批记录链接, 自定义字段 [共用错误原因字段]
-                Map body = TBConf.assembleCustomFieldName("checklist状态", "检查中");
-                tbClient.updateTaskCustomField(data.getString("taskId"), data.getString("creatorId"), body);
-                Map body2 = TBConf.assembleCustomFieldName("自检要素", result);
-                tbClient.updateTaskCustomField(data.getString("taskId"), data.getString("creatorId"), body2);
-            }
-            if (approve.equals(data.getString("tfsId"))) {
-                String deliverable = "65694e28b2fdeecdb23b5a2f"; // "659655758c54dca4b61c274e"; // 交付物任务字段ID
-                List<Map> attachments = TBConf.getTaskFieldValue(customfields, deliverable).stream().map(item -> {
-                    Map link = (Map) JSON.parse(String.valueOf(item.get("metaString")));
-                    // ppExt: 知识库绑定没有文件后缀, 宜搭识别目前仅能点击下载跳转预览, 添加统一docx后缀, 文档会自行区分
-                    return UtilMap.map("downloadUrl, name", link.get("url"), link.get("title") + ".docx");
-                }).collect(Collectors.toList());
-
-                String result = awClint.approve(tCode, data.getString("projectId"), attachments, data.getString("taskId"), data.getString("creatorId"), userId);
-                if (StringUtils.isBlank(result)) {
-                    return;
-                }
-                Map body2 = TBConf.assembleCustomFieldName("交付件描述", result);
-                tbClient.updateTaskCustomField(data.getString("taskId"), data.getString("creatorId"), body2);
-            }
+            awClint.doApprove(data);
         }
     }
 

+ 17 - 0
mjava-aiwei/src/main/java/com/malk/aiwei/server/AWServer.java

@@ -9,7 +9,24 @@ import java.util.Map;
 
 public class AWServer {
 
+    /**
+     * 任务卡片字段名称
+     */
+    public static final String TASK_ROLE = "资源名称";
+    public static final String TASK_CODE = "任务编号";
+    public static final String TASK_STAGE = "TR评审节点";
 
+    public static final String TASK_CHECK_LINK = "预检项";
+    public static final String TASK_CHECK_STATUS = "预检项检查状态";
+
+    public static final String TASK_APPROVE_ATTACHMENT = "交付件";
+    public static final String TASK_APPROVE_LINK = "交付件审批流程";
+
+    public static final String WORKFLOW_APPROVE = "已完成";
+
+    /**
+     * 艾为网关接口
+     */
     private static final String appKey = "AW394034j";
     private static final String secret = "RJbH7RMH3vllt4KDri303Mlw@df3434k";
 

+ 12 - 7
mjava-aiwei/src/main/java/com/malk/aiwei/service/AWClint.java

@@ -1,21 +1,26 @@
 package com.malk.aiwei.service;
 
-import java.util.List;
 import java.util.Map;
 
 public interface AWClint {
 
     /**
      * 交付物审批
-     * -
-     * ppExt
-     * 1. 宜搭附件传递 downloadUrl 和 name 即可实现在线预览
-     * 2. 知识库绑定没有文件后缀, 宜搭识别目前仅能点击下载跳转预览, 添加统一docx后缀, 文档会自行区分
      */
-    String approve(String tCode, String pCode, List<Map> docs, String taskId, String operatorId, String userId);
+    void doApprove(Map data);
+
+    /**
+     * 交付物审批回调
+     */
+    void approved(Map data);
 
     /**
      * 检查项check
      */
-    String check(String tCode, String pCode, String taskId, String operatorId, String userId);
+    Map doCheck(String taskId, boolean isTask);
+
+    /**
+     * 检查项回调
+     */
+    void checked(Map data);
 }

+ 232 - 69
mjava-aiwei/src/main/java/com/malk/aiwei/service/impl/AWImplClient.java

@@ -1,22 +1,26 @@
 package com.malk.aiwei.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
+import com.malk.aiwei.server.AWServer;
 import com.malk.aiwei.service.AWClint;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.dingtalk.DDConf;
 import com.malk.server.dingtalk.DDR_New;
+import com.malk.server.teambition.TBConf;
 import com.malk.service.aliwork.YDClient;
 import com.malk.service.aliwork.YDService;
+import com.malk.service.teambition.TBClient;
 import com.malk.utils.UtilMap;
 import com.malk.utils.UtilString;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -34,91 +38,250 @@ public class AWImplClient implements AWClint {
      * 交付物审批 [ppExt: 宜搭附件传递 downloadUrl 和 name 即可实现在线预览]
      */
     @Override
-    public String approve(String tCode, String pCode, List<Map> docs, String taskId, String operatorId, String userId) {
+    public void doApprove(Map data) {
 
-        log.info("交付物审批, {}", JSON.toJSONString(UtilMap.map("tCode, pCode, docs, taskId, operatorId, userId", tCode, pCode, docs, taskId, operatorId, userId)));
-        // 工作流tb配置了流转逻辑, 冗余稳定性
+        log.info("交付物审批, {}", data);
+        String projectId = UtilMap.getString(data, "projectId");
+        String workFlowApprove = _getWorkFlowStatus(projectId, AWServer.WORKFLOW_APPROVE);
+        if (!data.get("tfsId").equals(workFlowApprove)) {
+            return;
+        }
+        String pCode = UtilMap.getString(data, "projectId");
+        String creatorId = UtilMap.getString(data, "creatorId");
+        String taskId = UtilMap.getString(data, "taskId");
+        Map taskData = _getTaskFieldMap(UtilMap.getString(data, "taskId"), AWServer.TASK_CODE, AWServer.TASK_APPROVE_ATTACHMENT);
+        String tCode = UtilMap.getString(taskData, AWServer.TASK_CODE);
+        // 工作流tb虽然配置了流转逻辑, 冗余稳定性
         DDR_New ddr_new = ydClient.queryData(YDParam.builder()
+//                .formUuid("FORM-FBC1A390B4C348089020C763938A6F54RUNY")
                 .formUuid("FORM-812FD46AF391449A8F206EDB3221B38840UQ")
-                .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lqxuswzd, selectField_lqxuswze", tCode, pCode)))
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lqxuswzd, textField_lrncs2fu", tCode, pCode)))
                 .instanceStatus("RUNNING")
                 .build(), YDConf.FORM_QUERY.retrieve_search_process);
         if (ddr_new.getTotalCount() > 0) {
-            return "";
-        }
-        // 查询任务表与项目表
-        List<Map> tList = ydService.queryDataList_FormData("FORM-A25299893F614A6EAA672514D3A76BB0QDBF", UtilMap.map("textField_lqxu8st8", tCode));
-        if (tList.size() == 0) {
-            return "未配置交付物审批.";
+            return;
         }
-        List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", pCode));
-        if (pList.size() == 0) {
-            return "未匹配到项目主数据";
+
+        String result = "";
+        List<Map> tList = null;
+        Map rProject = null;
+        if (StringUtils.isBlank(tCode)) {
+            result = "无任务编码";
+        } else {
+//            tList = ydService.queryDataList_FormData("FORM-AB7263D2A12F4E01A871656F0D995BC96PR1", UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用"));
+            tList = ydService.queryDataList_FormData("FORM-A25299893F614A6EAA672514D3A76BB0QDBF", UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用"));
+            if (tList.size() == 0) {
+                result = "未配置交付物审批";
+            } else {
+//                List<Map> pList = ydService.queryDataList_FormData("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI", UtilMap.map("textField_lqxtykce", pCode));
+                List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", pCode));
+                if (pList.size() == 0) {
+                    result = "未匹配到项目主数据";
+                } else {
+                    rProject = pList.get(0);
+                }
+            }
+            /// 发起评审
+            if (StringUtils.isBlank(result)) {
+
+                List<Map> roles = (List<Map>) rProject.get("tableField_lqxtykcf");
+                Map formData = UtilMap.map("selectField_lqxuswzd, textField_lrncs2fu, radioField_lrnddfq6", tCode, pCode, "启用");
+                formData.put("attachmentField_lqxtebtq", _getDocs(taskData));
+                formData.put("selectField_lqxuswze", UtilMap.getString(rProject, "textField_lrj7vnxb")); // 项目编号
+                formData.put("textField_lqxuc9m4", UtilMap.getString(rProject, "textField_lqxtykcd")); // 项目名称
+                // 匹配任务编码与项目角色
+                List<Map<String, String>> compIds = Arrays.asList(  // 任务表角色, 交付物评审表: 角色, 审批人
+                        UtilMap.map("tsRole, prRole, prEmp", "multiSelectField_lrokzlo7, multiSelectField_lrokzlo7, employeeField_lqxtebtw"),
+                        UtilMap.map("tsRole, prRole, prEmp", "multiSelectField_lrokzlo8, multiSelectField_lrokzlo8, employeeField_lqxtebtx"),
+                        UtilMap.map("tsRole, prRole, prEmp", "multiSelectField_lrokzlo9, multiSelectField_lrokzlo9, employeeField_lqxtebty"));
+                Map rCondition = tList.get(0);
+                for (Map compId : compIds) {
+                    // ppExt: 宜搭多选若无值则不返回字段 [prd 角色多选, 会签逻辑]
+                    if (!rCondition.containsKey(compId.get("tsRole"))) {
+                        continue;
+                    }
+                    List<String> namesCondition = (List<String>) rCondition.get(compId.get("tsRole"));
+                    List<String> namesApproveRole = new ArrayList<>();
+                    List<String> namesApprover = new ArrayList<>();
+                    for (String name : namesCondition) {
+                        Optional optional = roles.stream().filter(item -> UtilString.equal(name, item.get("selectField_lqxu6bgf"))).findAny();
+                        if (optional.isPresent()) {
+                            Map detail = (Map) optional.get();
+                            if (ObjectUtil.isNotNull(detail.get("selectField_lqxu6bgf"))) {
+                                namesApproveRole.add(String.valueOf(detail.get("selectField_lqxu6bgf")));
+                            }
+                            if (ObjectUtil.isNotNull(detail.get("employeeField_lqxtykch_id"))) {
+                                namesApprover.addAll((List) detail.get("employeeField_lqxtykch_id"));
+                            }
+                        }
+                    }
+                    formData.put(compId.get("prRole"), namesApproveRole);
+                    formData.put(compId.get("prEmp"), namesApprover);
+                }
+                // 组装数据
+                Map<String, String> extra = (Map) tbClient.idMapQuery(creatorId, "dingTalk-user", ddConf.getCorpId()).get(0).get("extra");
+                UtilMap.putAll(formData, UtilMap.map("textField_lr3dlwsa, textField_lr3er4qb", taskId, creatorId));
+                String instanceId = (String) ydClient.operateData(YDParam.builder()
+//                        .formUuid("FORM-FBC1A390B4C348089020C763938A6F54RUNY")
+                        .formUuid("FORM-812FD46AF391449A8F206EDB3221B38840UQ")
+//                        .processCode("TPROC--YU966T91PIDH4XDR82OJC8GVOP7Z19PODTXQL6")
+                        .processCode("TPROC--RJC66SC1NEFHXJ0H770K0CF4WN1K21HQ706RL5")
+                        .formDataJson(JSON.toJSONString(formData))
+                        .userId(extra.get("userId"))
+                        .build(), YDConf.FORM_OPERATION.start);
+//                result = "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/processDetail?procInsId=" + instanceId;
+                result = "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/processDetail?procInsId=" + instanceId;
+            }
         }
-        List<Map> roles = (List<Map>) pList.get(0).get("tableField_lqxtykcf");
-        Map formData = UtilMap.map("selectField_lqxuswzd, selectField_lqxuswze, textField_lqxuc9m4", tCode, pCode, UtilMap.getString(pList.get(0), "textField_lqxtykcd"));
-        formData.put("attachmentField_lqxtebtq", docs);
-        // 匹配任务编码与项目角色
-        List<Map<String, String>> compIds = Arrays.asList(UtilMap.map("tsRole, prRole, prEmp", "selectField_lqxu76th, selectField_lqxu76th, employeeField_lqxtebtw"),
-                UtilMap.map("tsRole, prRole, prEmp", "selectField_lqxu76tj, selectField_lqxuw78q, employeeField_lqxtebtx"), // 任务表角色, 交付物评审表: 角色, 审批人
-                UtilMap.map("tsRole, prRole, prEmp", "selectField_lqxu76tk, selectField_lqxuw78r, employeeField_lqxtebty"));
-        for (Map compId : compIds) {
-
-            Optional optional = roles.stream().filter(item -> UtilString.equal(tList.get(0).get(compId.get("tsRole")), item.get("selectField_lqxu6bgf"))).findAny();
+        log.info("交付物结果, {}", result);
+        Map body = TBConf.assembleCustomFieldName(AWServer.TASK_APPROVE_LINK, result);
+        tbClient.updateTaskCustomField(taskId, creatorId, body);
+    }
+
+    /**
+     * 交付物审批回调
+     */
+    @Override
+    public void approved(Map data) {
+
+        log.info("交付物审批回调, {}", data);
+        String result = String.valueOf(data.get("approve"));
+        String workFlowId = _getWorkFlowStatus(String.valueOf(data.get("projectId")), result);
+        tbClient.updateTaskFlowStatus(String.valueOf(data.get("taskId")), String.valueOf(data.get("creatorId")), workFlowId, String.valueOf(data.get("approve")));
+    }
+
+    @Autowired
+    private TBClient tbClient;
+
+    @Autowired
+    private DDConf ddConf;
+
+    // 获取任务详情 todo 提取到 tbservice
+    private Map _getTaskFieldMap(String taskId, String... fieldNames) {
+
+        Map rTask = tbClient.queryTaskDetail(taskId, null, null).get(0);
+        List<Map> customfields = UtilMap.getList(rTask, "customfields");
+
+        // 任务编码字段ID
+        List<Map> customField = tbClient.queryProjectCustomField(String.valueOf(rTask.get("projectId")), null);
+
+        // 组装任务数据
+        Map result = UtilMap.map("task", rTask);
+        for (String filed : fieldNames) {
+            Optional optional = customField.stream().filter(item -> filed.equals(item.get("name"))).findAny();
             if (optional.isPresent()) {
-                Map detail = (Map) optional.get();
-                formData.put(compId.get("prRole"), detail.get("selectField_lqxu6bgf"));
-                formData.put(compId.get("prEmp"), detail.get("employeeField_lqxtykch_id"));
+                Map map = (Map) optional.get();
+                result.put(filed, TBConf.getTaskFieldValue_First(customfields, String.valueOf(map.get("id"))));
+                result.put(filed + "_id", map.get("id")); // ppExt: 返回字段ID
             }
         }
-        // 发起评审
-        UtilMap.putAll(formData, UtilMap.map("textField_lr3dlwsa, textField_lr3er4qb", taskId, operatorId));
-        String instanceId = (String) ydClient.operateData(YDParam.builder()
-                .formUuid("FORM-812FD46AF391449A8F206EDB3221B38840UQ")
-                .processCode("TPROC--RJC66SC1NEFHXJ0H770K0CF4WN1K21HQ706RL5")
-                .formDataJson(JSON.toJSONString(formData))
-                .userId(userId)
-                .build(), YDConf.FORM_OPERATION.start);
-//        return "记录: " + "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/processDetail?procInsId=" + instanceId;
-        return "记录: " + "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/processDetail?procInsId=" + instanceId;
+        return result;
+    }
+
+    // 匹配工作流名称, 获取ID
+    String _getWorkFlowStatus(String projectId, String workFlowStatusName) {
+
+        List<Map> customFlowStatus = tbClient.queryProjectCustomFlowStatus(projectId, UtilMap.map("q", workFlowStatusName));
+        McException.assertAccessException(customFlowStatus.isEmpty(), "工作流名称未匹配");
+        return String.valueOf(customFlowStatus.get(0).get("id"));
+    }
+
+    /**
+     * 获取知识库附件传递到宜搭 [ppExt]
+     * 1. 宜搭附件传递 downloadUrl 和 name 即可实现在线预览
+     * 2. 知识库绑定没有文件后缀, 宜搭识别目前仅能点击下载跳转预览, 添加统一docx后缀, 文档会自行区分
+     */
+    List<Map> _getDocs(Map taskData) {
+        Map rTask = UtilMap.getMap(taskData, "task");
+        List<Map> customfields = UtilMap.getList(rTask, "customfields");
+
+        String deliverable = String.valueOf(taskData.get(AWServer.TASK_APPROVE_ATTACHMENT + "_id")); // 交付物任务字段ID
+        List<Map> attachments = TBConf.getTaskFieldValue(customfields, deliverable).stream().map(item -> {
+            Map link = (Map) JSON.parse(String.valueOf(item.get("metaString")));
+            return UtilMap.map("downloadUrl, name", link.get("url"), link.get("title") + ".docx");
+        }).collect(Collectors.toList());
+        return attachments;
     }
 
     /**
      * 检查项check
+     *
+     * @param isTask 服务于任务自定义详情卡片, 否则为宜搭发起: 抛出错误信息
      */
     @Override
-    public String check(String tCode, String pCode, String taskId, String operatorId, String userId) {
+    public Map doCheck(String taskId, boolean isTask) {
 
-        log.info("交付物审批, {}", JSON.toJSONString(UtilMap.map("tCode, pCode, taskId, operatorId, userId", tCode, pCode, taskId, operatorId, userId)));
-        // 是否存在chek记录过滤
-        List<Map> cList = ydService.queryDataList_FormData("FORM-7A50EA1991CE4494949FF7E1D4592FFBOVUS", UtilMap.map("selectField_lqxuswzd, selectField_lqxuswze", tCode, pCode));
-        if (cList.size() > 0) {
-            return "";
+        log.info("检查项check, {}", taskId);
+        Map taskData = _getTaskFieldMap(taskId, AWServer.TASK_CODE, AWServer.TASK_CHECK_LINK, AWServer.TASK_ROLE, AWServer.TASK_STAGE);
+        String checkLink = UtilMap.getString(taskData, AWServer.TASK_CHECK_LINK);
+        /// prd 预检项持续维护需要重新匹配, 任务号和主数据判定为非法, 无需重新刷新
+        if (isTask && (StringUtils.isNotBlank(checkLink) && !"未配置预检项".equals(checkLink))) {
+            return UtilMap.map("result", "链接已加载");
         }
-        // 查询任务编码检查项与任务
-        List<Map> tList = ydService.queryFormData_all(YDParam.builder()
-                .formUuid("FORM-1A5D4D7FBF88409B956EBE51F9342A6BKOLP")
-                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lqxu8st8", tCode)))
-                .build());
-        if (tList.size() == 0) {
-            return "未配置检查项.";
+        Map rTask = UtilMap.getMap(taskData, "task");
+        String creatorId = UtilMap.getString(rTask, "creatorId");
+        String tCode = UtilMap.getString(taskData, AWServer.TASK_CODE);
+        String pCode = UtilMap.getString(rTask, "projectId");
+
+        String result = "";
+        List<Map> tList = null;
+        Map rProject = null;
+        if (StringUtils.isBlank(tCode)) {
+            result = "无任务编码";
+        } else {
+            tList = ydService.queryFormData_all(YDParam.builder()
+//                    .formUuid("FORM-E6CB042D7929448888AE5E2B27631E57IVPM")
+                    .formUuid("FORM-1A5D4D7FBF88409B956EBE51F9342A6BKOLP")
+                    .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用")))
+                    .build());
+            if (tList.size() == 0) {
+                result = "未配置预检项";
+            } else {
+//                List<Map> pList = ydService.queryDataList_FormData("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI", UtilMap.map("textField_lqxtykce", pCode));
+                List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", pCode));
+                if (pList.size() == 0) {
+                    result = "未匹配到项目主数据";
+                } else {
+                    rProject = pList.get(0);
+//                    result = "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/workbench/FORM-7B63BB056145452F8BC0A2C52492DE00QVBH?taskId=" + taskId;
+                    result = "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/workbench/FORM-6E2C0D1197264B8AA23EB3FECAE7344B00BN?taskId=" + taskId;
+                }
+            }
         }
-        List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", pCode));
-        if (pList.size() == 0) {
-            return "未匹配到项目主数据.";
+        log.info("检查项结果, {}", result);
+        if (isTask) {
+            if (!checkLink.equals(result)) {
+                Map body = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_LINK, result);
+                tbClient.updateTaskCustomField(taskId, creatorId, body);
+            }
+            return UtilMap.map("result", result);
         }
-        Map formData = UtilMap.map("selectField_lqxuswzd, selectField_lqxuswze, textField_lqxuc9m4", tCode, pCode, UtilMap.getString(pList.get(0), "textField_lqxtykcd"));
-        // 填充检查项目, 填充子表
-        List<Map> checkList = tList.stream().map(item -> UtilMap.map("textField_lqxxgj4u", item.get("textField_lqxxgj4u"))).collect(Collectors.toList());
-        formData.put("tableField_lqxxgj4s", checkList);
-        // 发起评审
-        UtilMap.putAll(formData, UtilMap.map("textField_lr3dlwsa, textField_lr3er4qb", taskId, operatorId));
-        String instanceId = (String) ydClient.operateData(YDParam.builder()
-                .formUuid("FORM-7A50EA1991CE4494949FF7E1D4592FFBOVUS")
-                .processCode("TPROC--AKA66FB1XHFHN82QEFIQ591SNJ5W3AMBJ06RL9")
-                .formDataJson(JSON.toJSONString(formData))
-                .userId(userId)
-                .build(), YDConf.FORM_OPERATION.start);
-        return "记录: " + "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/processDetail?procInsId=" + instanceId;
+        McException.assertAccessException(ObjectUtil.isNull(rProject), result);
+
+        Map formData = UtilMap.map("selectField_lqxuswzd, textField_lrndwu00, textField_lr3dlwsa, textField_lr3er4qb", tCode, pCode, taskId, creatorId);
+        // 项目信息
+        formData.putAll(UtilMap.map("selectField_lqxuswze, textField_lrndwu07, textField_lqxuc9m4", UtilMap.getString(rProject, "textField_lrj7vnxb"), UtilMap.getString(rProject, "textareaField_lrj7vnxl"), UtilMap.getString(rProject, "textField_lqxtykcd")));
+        // 任务信息 todo  userInfo 取值
+        Map<String, String> extra = (Map) tbClient.idMapQuery(creatorId, "dingTalk-user", ddConf.getCorpId()).get(0).get("extra");
+        formData.putAll(UtilMap.map("textField_lrndwu09, textField_lrndwu0a, textField_lrndwu0b, employeeField_lrndwu0e", rTask.get("content"), taskData.get(AWServer.TASK_STAGE), taskData.get(AWServer.TASK_ROLE), Arrays.asList(UtilMap.map("value, name", extra.get("userId"), extra.get("userId")))));
+        // 返回检查项
+        formData.put("tableField_lqxxgj4s", tList);
+        return formData;
+    }
+
+    /**
+     * 检查项回调
+     */
+    @Override
+    public void checked(Map data) {
+
+        log.info("检查项回调, {}", data);
+        Map body = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_STATUS, "已检查");
+        tbClient.updateTaskCustomField(String.valueOf(data.get("taskId")), String.valueOf(data.get("creatorId")), body);
+
+//        String result = "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/formDetail?formInstId=" + data.get("formInstId");
+        String result = "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/formDetail?formInstId=" + data.get("formInstId");
+        Map body2 = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_LINK, result);
+        tbClient.updateTaskCustomField(String.valueOf(data.get("taskId")), String.valueOf(data.get("creatorId")), body2);
     }
 }

+ 28 - 28
mjava-aiwei/src/main/resources/application-dev.yml

@@ -47,40 +47,40 @@ logging:
   file:
     path: /Users/malk/server/_Tool/var/mjava/log
 
-## dingtalk
-#dingtalk:
-#  agentId: 2691784047
-#  appKey: dinghbynhnd2dbgypmsa
-#  appSecret: Kl5Xw8x0TlEIlvcJuUkYZD18UTTShJmfdKrAIpY8oX-Q_tazyUKA28nQh7dG5-mq
-#  corpId: ding321c72787fffc78b35c2f4657eb6378f
-#  aesKey:
-#  token:
-#  operator: ""   # OA管理员账号
-#
-## aliwork
-#aliwork:
-#  appType: "APP_H7WUJTKB448F9IBDC6C4"
-#  systemToken: "DHA66081DN6GRFNC6GTRW5NIJS082ZF0UN9PLLF"
-
-# teambition
-teambition:
-  AppID: 65956b5dd0ac095d62d0e592
-  AppSecret: gjQUoqKa1PHjTiyQFFuachfqKPyNeacA
-  TenantId: 6034c885e71842e1e5bb5218        # 管理后台 - 企业xx - 企业ID
-  OperatorId: 5e698cca57e7c1003626f3ff      # 公共账号, 需要有操作权限 [牧语]
-
 # dingtalk
 dingtalk:
-  agentId: 2848797049
-  appKey: dingbqy1qugrihao43dl
-  appSecret: UUaTKTWgLdduHvMSl0ipm19f_PDarHLHqnpz4vFZXjkkmFNmfWuwoPF1evjIRwvd
-  corpId: ding5fcad818b0d9f62c35c2f4657eb6378f
+  agentId: 2691784047
+  appKey: dinghbynhnd2dbgypmsa
+  appSecret: Kl5Xw8x0TlEIlvcJuUkYZD18UTTShJmfdKrAIpY8oX-Q_tazyUKA28nQh7dG5-mq
+  corpId: ding321c72787fffc78b35c2f4657eb6378f
   aesKey:
   token:
   operator: ""   # OA管理员账号
 
 # aliwork
 aliwork:
-  appType: "APP_R5EBUF2FPN3Y8DRF93M4"
-  systemToken: "ON566NC1VNIHPANP9TNVHB3TBIWS3E0TUZ5RLF3"
+  appType: "APP_H7WUJTKB448F9IBDC6C4"
+  systemToken: "DHA66081DN6GRFNC6GTRW5NIJS082ZF0UN9PLLF"
+
+# teambition
+teambition:
+  AppID: 65956b5dd0ac095d62d0e592
+  AppSecret: gjQUoqKa1PHjTiyQFFuachfqKPyNeacA
+  TenantId: 6034c885e71842e1e5bb5218        # 管理后台 - 企业xx - 企业ID
+  OperatorId: 5e698cca21f5ad70dfba7d2b      # 公共账号, 需要有操作权限 [牧语]
+
+## dingtalk
+#dingtalk:
+#  agentId: 2848797049
+#  appKey: dingbqy1qugrihao43dl
+#  appSecret: UUaTKTWgLdduHvMSl0ipm19f_PDarHLHqnpz4vFZXjkkmFNmfWuwoPF1evjIRwvd
+#  corpId: ding5fcad818b0d9f62c35c2f4657eb6378f
+#  aesKey:
+#  token:
+#  operator: ""   # OA管理员账号
+#
+## aliwork
+#aliwork:
+#  appType: "APP_R5EBUF2FPN3Y8DRF93M4"
+#  systemToken: "ON566NC1VNIHPANP9TNVHB3TBIWS3E0TUZ5RLF3"
 

+ 39 - 9
mjava-lemeng/src/main/java/com/malk/lemeng/service/impl/LMImplService.java

@@ -13,6 +13,7 @@ import com.malk.service.dingtalk.DDClient_Personnel;
 import com.malk.utils.UtilFile;
 import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -107,6 +108,8 @@ public class LMImplService implements LMService {
     @Autowired
     private YDService ydService;
 
+    private static final int BUDGET_PER = 200;
+
     /**
      * 同步部门信息
      */
@@ -126,9 +129,9 @@ public class LMImplService implements LMService {
             }
             Map info = ddClient_contacts.getDepartmentInfo(ddClient.getAccessToken(), deptId);
             Map formData = UtilMap.map("textField_lpcff8zu, numberField_lr70cqsl, numberField_lr70cqsk", info.get("name"), info.get("parent_id"), info.get("dept_id"));
-            // todo 部门ID写入需要是string集合\数组
+            // todo 部门ID写入需要是string集合\数组, 封装
             formData.putAll(UtilMap.map("employeeField_lpmbmyaa, departmentSelectField_lpaks312", info.get("dept_manager_userid_list"), Arrays.asList(String.valueOf(info.get("dept_id")))));//            float budget = userIds.size() * 200; // 部门人均
-            float budget = userIds.size() * 200; // 部门人均
+            float budget = userIds.size() * BUDGET_PER; // 部门人均
             formData.putAll(UtilMap.map("numberField_lr71bkuj, employeeField_lr71bkui, numberField_lr71mvbk", userIds.size(), userIds, budget));
             // Upsert操作, 记录当月预算
             Optional optional = dataList.stream().filter(item -> deptId == UtilMap.getLong(item, "numberField_lr70cqsk")).findAny();
@@ -149,6 +152,15 @@ public class LMImplService implements LMService {
         }
     }
 
+    /// 涉及行政归属, 拆分规则
+    private void updateBalance(Map item, int budget, float quota) {
+        item.put("numberField_lpaks318", UtilMap.getFloat(item, "numberField_lpaks318") + budget); // 总经费
+        item.put("numberField_lpayajrn", UtilMap.getFloat(item, "numberField_lpayajrn") + budget); // 可用余额
+        item.put("numberField_lr7yq38c", UtilMap.getFloat(item, "numberField_lr7yq38c") + budget); // 修改前总金额
+        item.put("numberField_lr71mvbk", UtilMap.getFloat(item, "numberField_lr71mvbk") + budget); // 当月预计预算
+        item.put("numberField_lr71bkuj", UtilMap.getInt(item, "numberField_lr71bkuj") + quota);    // 部门人数
+    }
+
     /**
      * 部门预算统计
      */
@@ -159,7 +171,25 @@ public class LMImplService implements LMService {
         List<Map> dataList = ydService.queryFormData_all(YDParam.builder()
                 .formUuid("FORM-B6F662B18C3F4D7D855CFE50243394AFQPOH")
                 .build());
-        // prd 非独立预算部门, 累计到父部门, 若父部门为空, 持续往上累加
+        // prd 不存在一人多部门情况, 若是涉及行政归属则手动维护
+        List<Map> manualList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid("FORM-A192B0134C184B1A84A791F322AA4D60N4F2")
+                .build());
+        for (Map data : manualList) {
+            String userId = String.valueOf(UtilMap.getList(data, "employeeField_lroz3y2w_id").get(0));
+            Map srcDpet = dataList.stream().filter(item -> UtilMap.getList(data, "employeeField_lr71bkui_id").contains(userId)).findAny().get();
+            updateBalance(srcDpet, -BUDGET_PER, -1); // 去除原部门个人金额
+
+            boolean multi = StringUtils.isNotBlank(UtilMap.getString(data, "numberField_lroz3y37"));
+            if (multi) {
+                Map curDpet = dataList.stream().filter(item -> UtilMap.getList(data, "numberField_lroz3y37").contains(item.get("numberField_lr70cqsk"))).findAny().get();
+                updateBalance(curDpet, BUDGET_PER / 2, 0.5f); // 累加部门2个人金额一半
+            }
+            Map curDpet = dataList.stream().filter(item -> UtilMap.getList(data, "numberField_lr70cqsk").contains(item.get("numberField_lr70cqsk"))).findAny().get();
+            updateBalance(curDpet, multi ? BUDGET_PER / 2 : BUDGET_PER, multi ? 0.5f : 1f); // 累加部门1个人金额
+        }
+
+        // prd todo 非独立预算部门, 累计到父部门, 若父部门为空, 持续往上累加
         dataList.forEach(item -> {
             if ("是".equals(item.get("radioField_lpaks316"))) {
                 int budget = UtilMap.getInt(item, "numberField_lr71mvbk");
@@ -168,14 +198,14 @@ public class LMImplService implements LMService {
                 item.put("numberField_lpaks318", UtilMap.getFloat(item, "numberField_lpaks318") + budget);
                 item.put("numberField_lpayajrn", UtilMap.getFloat(item, "numberField_lpayajrn") + budget);
                 item.putAll(UtilMap.map("employeeField_lr71bkui, departmentSelectField_lpaks312", item.get("employeeField_lr71bkui_id"), item.get("departmentSelectField_lpaks312_id"))); // 非常规组件数据处理
-                ydClient.operateData(YDParam.builder()
-                        .formInstanceId(UtilMap.getString(item, "instanceId"))
-                        .updateFormDataJson(JSON.toJSONString(item))
-                        .build(), YDConf.FORM_OPERATION.update);
+//                ydClient.operateData(YDParam.builder()
+//                        .formInstanceId(UtilMap.getString(item, "instanceId"))
+//                        .updateFormDataJson(JSON.toJSONString(item))
+//                        .build(), YDConf.FORM_OPERATION.update);
             }
-            // todo 一人多部门情况
-
         });
+
+
     }
 
     /// test

+ 2 - 0
mjava/src/main/java/com/malk/delegate/TBEvent.java

@@ -13,6 +13,8 @@ public interface TBEvent {
 
     /**
      * 任务回调事件  [异步]
+     * ppExt
+     * 1. 若存在前后置, 未完成子任务, 点击完成TB会自动切换为未完成, 此种状态下不会触发任务回调
      */
     void callBackTask(JSONObject eventJson);
 

+ 22 - 0
mjava/src/main/java/com/malk/service/teambition/TBClient.java

@@ -130,4 +130,26 @@ public interface TBClient {
      * @apiNote https://open.teambition.com/docs/apis/6321c6d2912d20d3b5a4a579
      */
     Map updateTaskFlowStatus(String taskId, String operatorId, String taskflowstatusId, String tfsUpdateNote);
+
+
+    /**
+     * 获取自定义字段
+     *
+     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a497f6
+     */
+    List<Map> queryProjectCustomField(String projectId, Map body);
+
+    /**
+     * 搜索项目工作流状态
+     *
+     * @apiNote https://open.teambition.com/api/v3/project/{projectId}/taskflowstatus/search
+     */
+    List<Map> queryProjectCustomFlowStatus(String projectId, Map body);
+
+    /**
+     * 搜索项目工作流 [ppExt: 即任务类型]
+     *
+     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49fc3
+     */
+    List<Map> queryProjectCustomFlow(String projectId, Map body);
 }

+ 21 - 0
mjava/src/main/java/com/malk/service/teambition/impl/TBClientImpl.java

@@ -202,4 +202,25 @@ public class TBClientImpl implements TBClient {
         TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/v3/task/" + taskId + "/taskflowstatus", initHeaderToken(operatorId), body, TBR.class);
         return (Map) tbr.getResult();
     }
+
+    @Override
+    public List<Map> queryProjectCustomField(String projectId, Map body) {
+        UtilMap.putNotNull(body, "pageSize", 500);
+        TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/customfield/search", initHeaderToken(), body, TBR.class);
+        return (List<Map>) tbr.getResult();
+    }
+
+    @Override
+    public List<Map> queryProjectCustomFlowStatus(String projectId, Map body) {
+        UtilMap.putNotNull(body, "pageSize", 500);
+        TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/taskflowstatus/search", initHeaderToken(), body, TBR.class);
+        return (List<Map>) tbr.getResult();
+    }
+
+    @Override
+    public List<Map> queryProjectCustomFlow(String projectId, Map body) {
+        UtilMap.putNotNull(body, "pageSize", 500);
+        TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/taskflow/search", initHeaderToken(), body, TBR.class);
+        return (List<Map>) tbr.getResult();
+    }
 }