Ver código fonte

艾为更新

pruple_boy 1 ano atrás
pai
commit
b49a002007

+ 36 - 0
mjava-aiwei/src/main/java/com/malk/aiwei/controller/TBxYDController.java

@@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Slf4j
 @RestController
@@ -114,6 +115,20 @@ public class TBxYDController {
         return McR.success();
     }
 
+    /**
+     * 删除前后置依赖
+     */
+    @PostMapping("project/remove/dependencies")
+    McR removeDependencies(HttpServletRequest request) {
+
+        Map<String, ?> data = UtilServlet.getParamMap(request);
+        log.info("删除前后置依赖, {}", data);
+        McException.assertParamException_Null(data, "projectId", "trNode");
+
+        awClint.removeDependencies(UtilMap.getString(data, "projectId"), (List<String>) JSON.parse(UtilMap.getString(data, "trNode")));
+        return McR.success();
+    }
+
     /**
      * 手动触发, 同步预检项
      */
@@ -174,8 +189,29 @@ public class TBxYDController {
         return McR.success(rsp);
     }
 
+    // 获取项目自定义字段ID, 格式 { 名称: id } todo 提取
+    Map<String, String> getProjectCFID(String projectId, List<String> names) {
+        List<Map> customField = tbClient.queryProjectCustomField(projectId, null);
+        List tList = customField.stream().filter(item -> names.contains(item.get("name"))).collect(Collectors.toList());
+        return (Map<String, String>) tList.stream().reduce(UtilMap.empty(), (acc, cur) -> {
+            ((Map) acc).put(((Map) cur).get("name"), ((Map) cur).get("id"));
+            return acc;
+        });
+    }
+
     @GetMapping("tmp")
     McR tmp() {
+
+        String projectId = "659376ba950780b816c33d3b";
+
+//        tbClient.queryGanttBaseline(projectId, null);
+//        String cfid = getProjectCFID(projectId, Arrays.asList(AWServer.TASK_CODE)).get(AWServer.TASK_CODE);
+//        String tql = "cf:" + cfid + " = " + "TR1-01";
+//        tbClient.queryProjectTaskList(projectId, UtilMap.map("q", tql), null);
+//        tbClient.queryProjectRoles(projectId)
+//        tbClient.queryProjectMember(projectId, null);
+
+        awClint.test();
         return McR.success();
     }
 }

+ 4 - 1
mjava-aiwei/src/main/java/com/malk/aiwei/service/AWClint.java

@@ -2,6 +2,7 @@ package com.malk.aiwei.service;
 
 import com.malk.server.aliwork.YDParam;
 
+import java.util.List;
 import java.util.Map;
 
 public interface AWClint {
@@ -44,7 +45,7 @@ public interface AWClint {
     /**
      * 项目迁移: 删除依赖项
      */
-    void removeDependencies(String projectId, String trNode);
+    void removeDependencies(String projectId, List<String> trNode);
 
     /**
      * 同步预检项
@@ -64,4 +65,6 @@ public interface AWClint {
      * @param type 预检项分类(0-经验库、1-技术评审要素表, 2-TR评审要素表)
      */
     void syncCheckList(int type);
+
+    void test();
 }

+ 41 - 10
mjava-aiwei/src/main/java/com/malk/aiwei/service/impl/AWImplClient.java

@@ -356,7 +356,7 @@ public class AWImplClient implements AWClint {
         if (StringUtils.isNotBlank(projectCode)) {
             ydParam.setSearchFieldJson(JSON.toJSONString(UtilMap.map("textField_le6o88w0", projectCode)));
         }
-        // prd 客户系统主数据, 是全量定时从mdmg更新, 因此不能增量
+        // prd 客户系统主数据, 是全量定时从mdm更新, 因此不能增量
         List<Map> mapBaseList = ydService.queryFormData_all(ydParam);
         if (StringUtils.isNotBlank(projectCode)) {
             mapBaseList = mapBaseList.stream().filter(item -> projectCode.equals(item.get("textField_le6o88w0"))).collect(Collectors.toList());
@@ -405,7 +405,7 @@ public class AWImplClient implements AWClint {
             if (projectMaps.size() > 0) {
                 ydParam2.setFormInstanceId(String.valueOf(projectMaps.get(0).get("instanceId")));
                 ydClient.operateData(ydParam2, YDConf.FORM_OPERATION.update);
-                // 保留tb项目号, 避免冲重复通过模板参加项目 todo::: 临时bug
+                // 保留tb项目号, 避免冲重复通过模板参加项目
                 formData.put("textField_lqxtykce", UtilMap.getString(projectMaps.get(0), "textField_lqxtykce"));
                 formData.put("formInstanceId", projectMaps.get(0).get("instanceId"));
             } else {
@@ -414,6 +414,11 @@ public class AWImplClient implements AWClint {
             }
             log.info("同步项目主数据", projectCode);
         }
+        // tb项目成员更新
+        String projectId = UtilMap.getString(formData, "textField_lqxtykce");
+        if (StringUtils.isBlank(projectId) && StringUtils.isBlank(projectCode)) {
+            _syncProjectRole(formData, projectId);
+        }
         return formData;
     }
 
@@ -443,6 +448,11 @@ public class AWImplClient implements AWClint {
                     .updateFormDataJson(JSON.toJSONString(UtilMap.map("textField_lqxtykce", projectId)))
                     .build(), YDConf.FORM_OPERATION.update);
         }
+        _syncProjectRole(formData, projectId);
+    }
+
+    // 同步TB项目成员 todo 群成员
+    void _syncProjectRole(Map formData, String projectId) {
         // prd TB项目成员, 项目经理设置为管理者
         List<String> pmUserId = new ArrayList<>();
         List<String> roleIds = new ArrayList<>();
@@ -461,16 +471,26 @@ public class AWImplClient implements AWClint {
         // 钉钉人员ID转TB人员ID
         roleIds = _convertUserId(roleIds, false);
         tbClient.createProjectMember(projectId, roleIds, tbConf.getOperatorId());
-        // todo 删除项目成员
 
+        // prd 不做删除, 离职自动退出, 避免临时交接不可见的问题. 但需要移除项目经理权限
+        String pmRoleId = _getProjectRoleId(projectId, AWServer.PROJECT_PM_ROLE);
+        List<Map> roleList = tbClient.queryProjectMember(projectId, UtilMap.map("projectRoleId", pmRoleId));
+        for (Map role : roleList) {
+            List<String> tRoleIds = UtilMap.getList(role, "roleIds");
+            tRoleIds.remove(pmRoleId);
+            if (tRoleIds.isEmpty()) {
+                tRoleIds.add(_getProjectRoleId(projectId, "项目成员"));
+            }
+            tbClient.updateProjectMember(Arrays.asList(UtilMap.getString(role, "userId")), tRoleIds, projectId);
+        }
         // 指定项目经理为编辑权限
         if (!pmUserId.isEmpty()) {
-            tbClient.updateProjectMember(_convertUserId(pmUserId, false), Arrays.asList(_getProjectRoleId(projectId, AWServer.PROJECT_PM_ROLE)), projectId);
+            tbClient.updateProjectMember(_convertUserId(pmUserId, false), Arrays.asList(pmRoleId), projectId);
         }
         log.info("TB项目信息, {}, {}", projectId, roleIds.size());
     }
 
-    // todo 提取方法, 并封装为 ...roleName
+    // todo 提取方法, 参考 getProjectCFID 实现
     private String _getProjectRoleId(String projectId, String roleName) {
         List<Map> roles = tbClient.queryProjectRoles(projectId);
         Optional optional = roles.stream().filter(item -> roleName.equals(item.get("name"))).findAny();
@@ -530,21 +550,27 @@ public class AWImplClient implements AWClint {
      * 项目迁移: 删除依赖项
      */
     @Override
-    public void removeDependencies(String projectId, String trNode) {
+    public void removeDependencies(String projectId, List<String> trNode) {
 
-        log.info("删除依赖项 projectId = {}, trNode = {}", projectId, trNode);
         // 任务编码字段ID
         List<Map> customField = tbClient.queryProjectCustomField(projectId, null);
         tbClient.queryProjectTaskList(projectId, null, taskList -> {
             for (Map task : taskList) {
 
-                // 获取资源名称对应的项目角色
-                Optional optional = customField.stream().filter(item -> AWServer.TASK_ROLE.equals(item.get("name"))).findAny();
+                Optional optional = customField.stream().filter(item -> "TR评审节点".equals(item.get("name"))).findAny();
                 if (!optional.isPresent()) {
                     continue;
                 }
                 List<Map> customfields = (List<Map>) task.get("customfields");
-                String roleName = TBConf.getTaskFieldValue_First(customfields, UtilMap.getString((Map) optional.get(), "id"));
+                String trName = TBConf.getTaskFieldValue_First(customfields, UtilMap.getString((Map) optional.get(), "id"));
+                if (trNode.contains(trName)) {
+                    String taskId = UtilMap.getString(task, "id");
+                    List<Map> dependencies = tbClient.queryTaskDependency(taskId, null);
+                    log.info("taskID = {}, trNode, {}, 依赖数量: {}", taskId, trName, dependencies.size());
+                    for (Map dependency : dependencies) {
+                        tbClient.removeTaskDependency(UtilMap.getString(dependency, "id"), tbConf.getOperatorId());
+                    }
+                }
             }
             return true;
         });
@@ -655,6 +681,11 @@ public class AWImplClient implements AWClint {
                 break;
         }
     }
+
+    @Override
+    public void test() {
+
+    }
 }
 
 

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

@@ -78,8 +78,8 @@ teambition:
 #  aesKey:
 #  token:
 #  operator: ""   # OA管理员账号
-#
-# aliwork
+
+## aliwork
 #aliwork:
 #  appType: "APP_R5EBUF2FPN3Y8DRF93M4"
 #  systemToken: "ON566NC1VNIHPANP9TNVHB3TBIWS3E0TUZ5RLF3"

+ 1 - 1
mjava-aiwei/src/main/resources/application-prod.yml

@@ -6,7 +6,7 @@ server:
 
 # condition
 spel:
-  scheduling: false        # 定时任务是否执行
+  scheduling: true         # 定时任务是否执行
   multiSource: false       # 是否多数据源配置
 
 spring:

+ 34 - 5
mjava/src/main/java/com/malk/service/teambition/TBClient.java

@@ -81,7 +81,7 @@ public interface TBClient {
     /**
      * 获取项目角色列表
      *
-     * @return { result:  { level } }   项目角色等级: 0=成员, 1=管理员, 2=拥有者
+     * @return { result:  { level } }   项目角色等级: 0=项目成员, 1=项目管理员, 2=项目拥有者, -3:任务访客
      * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49b8f
      */
     List<Map> queryProjectRoles(String projectId);
@@ -90,11 +90,18 @@ public interface TBClient {
      * 修改项目成员的角色
      *
      * @param roleIds 角色ID列表 [通过 获取项目角色列表 获取]
-     * @return { result:  { role } }   项目角色: 0=成员, 1=管理员, 2=拥有者
+     * @return { result:  { role } }   项目角色等级: 0=项目成员, 1=项目管理员, 2=项目拥有者, -3:任务访客
      * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a49942
      */
     List<Map> updateProjectMember(List<String> userIds, List<String> roleIds, String projectId);
 
+    /**
+     * 获取项目成员列表
+     *
+     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a49906
+     */
+    List<Map> queryProjectMember(String projectId, Map body);
+
     /**
      * 查询任务详情
      *
@@ -116,7 +123,9 @@ public interface TBClient {
     /**
      * 查询项目任务
      *
-     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49ec1
+     * @param param:q ppExt TQL 格式 cf:查询项目字段ID = TR1-01
+     * @apiNote API: https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49ec1
+     * @apiNote TQL: https://open.teambition.com/docs/documents/639982966b99d5002b510f0b
      */
     List<Map> queryProjectTaskList(String projectId, Map param, QueryAll lambda);
 
@@ -156,9 +165,8 @@ public interface TBClient {
      */
     Map updateTaskFlowStatus(String taskId, String operatorId, String taskflowstatusId, String tfsUpdateNote);
 
-
     /**
-     * 获取自定义字段
+     * 获取自定义字段 ppExt: 目前原厂还未开放企业级字段, 若同一个项目存在不同项目类型, 建议使用企业字段, 保证ID的唯一性
      *
      * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a497f6
      */
@@ -178,6 +186,27 @@ public interface TBClient {
      */
     List<Map> queryProjectCustomFlow(String projectId, Map body);
 
+    /**
+     * 获取依赖项
+     *
+     * @apiNote https://open.teambition.com/docs/apis/63613a18912d20d3b5296e6d
+     */
+    List<Map> queryTaskDependency(String taskId, Map body);
+
+    /**
+     * 删除任务依赖
+     *
+     * @apiNote https://open.teambition.com/docs/apis/65e5c202912d20d3b50a63ad
+     */
+    Map removeTaskDependency(String dependencyId, String operatorId);
+
+    /**
+     * 获取项目下甘特图基线
+     *
+     * @apiNote https://open.teambition.com/docs/apis/6424f885912d20d3b50b759b
+     */
+    List<Map> queryGanttBaseline(String projectId, Map body);
+
     /**
      * 查询全部数据 [函数回调]
      * - ppExt -

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

@@ -175,6 +175,14 @@ public class TBClientImpl implements TBClient {
         return (List<Map>) tbr.getResult();
     }
 
+    @Override
+    public List<Map> queryProjectMember(String projectId, Map param) {
+        param = UtilMap.put(param, "pageSize", TBConf.PAGE_SIZE_LIMIT);
+        param.put("limit", TBConf.PAGE_SIZE_LIMIT);
+        TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/member", initHeaderToken(), param, TBR.class);
+        return (List<Map>) tbr.getResult();
+    }
+
     @Override
     public List<Map> queryProjectRoles(String projectId) {
         Map param = UtilMap.map("pageSize", TBConf.PAGE_SIZE_LIMIT);
@@ -260,4 +268,25 @@ public class TBClientImpl implements TBClient {
         TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/taskflow/search", initHeaderToken(), body, TBR.class);
         return (List<Map>) tbr.getResult();
     }
+
+    @Override
+    public List<Map> queryTaskDependency(String taskId, Map body) {
+        body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
+        body.put("taskId", taskId);
+        TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "v3/task/dependency", initHeaderToken(), body, TBR.class);
+        return (List<Map>) tbr.getResult();
+    }
+
+    @Override
+    public Map removeTaskDependency(String dependencyId, String operatorId) {
+        TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/task/dependency/" + dependencyId + "/delete", initHeaderToken(operatorId), null, TBR.class);
+        return (Map) tbr.getResult();
+    }
+
+    @Override
+    public List<Map> queryGanttBaseline(String projectId, Map body) {
+        body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
+        TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/gantt/baseline", initHeaderToken(), UtilMap.map("projectId", projectId), TBR.class);
+        return (List<Map>) tbr.getResult();
+    }
 }