news 2026/6/9 16:07:11

项目管理中如何项目完成后自动关闭所有任务?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
项目管理中如何项目完成后自动关闭所有任务?

当项目被标记为“已完成”时,可能仍然存在一些未完成的任务,例如未标记为已完成的重复任务、不再相关的任务或项目结束后不再需要关注的任务。

为了确保项目反映其最终状态,您可以使用任务工作流程规则,在项目达到“已完成”状态后自动关闭所有未完成的任务。

要进行此设置,请执行以下步骤:

首先,使用以下权限范围创建与 Zoho Projects 的连接:

ZohoProjects.tasks.ALL

ZohoProjects.projects.READ

ZohoProjects.portals.READ

ZohoProjects.milestones.ALL

创建一个自定义函数并添加以下 Deluge 脚本。将“xxxxxxxxx”替换为您的 Zoho Projects 连接名称,并映射下面列出的参数。

  1. 以下脚本将删除任务重复项并关闭项目中的所有任务。在以下脚本中,连接名称为“closealltasks”。

    / TODO: Please create a connection for the Zoho Projects service with the scopes "ZohoProjects.tasks.ALL, ZohoProjects.projects.READ, ZohoProjects.portals.READ, ZohoProjects.milestones.ALL". Replace 'xxxxxxxxx' with the connection name. Click this link below to learn how to create the connection.

  2. // Link - https://help.zoho.com/portal/en/kb/projects/integration/connections/articles/connections-23-5-2022#How_to_establish_a_Connection

  3. // TODO: Replace the status name (Closed status type) in Line No. 6, if needed.

  4. projectsAPIEndPoint = "https://projectsapi.zoho.com/restapi";

  5. projectsv3APIEndPoint = "https://projectsapi.zoho.com/api/v3";

  6. statusName = "Closed";

  7. statusId = null;

  8. /* Close all tasks */

  9. //Fetch task layouts

  10. taskLayoutDetails = invokeurl

  11. [

  12. url :projectsAPIEndPoint + "/portal/" + portalId + "/projects/" + projectId + "/tasklayouts"

  13. type :GET

  14. connection:"closealltasks"

  15. ];

  16. // info taskLayoutDetails;

  17. if(taskLayoutDetails != null && taskLayoutDetails.get("status_details") != null)

  18. {

  19. statusDetails = taskLayoutDetails.get("status_details");

  20. for each status in statusDetails

  21. {

  22. if(status.get("name").equalsIgnoreCase(statusName))

  23. {

  24. // Fetch task status id based on status name

  25. statusId = status.get("id");

  26. info status.get("name") + " : " + statusId;

  27. break;

  28. }

  29. }

  30. }

  31. if(statusId != null)

  32. {

  33. indexValue = 1;

  34. rangeValue = 100;

  35. loop = {1,2,3,4,5,6,7,8,9,10};

  36. predStatusMap = Map();

  37. // This loop fetches up to 300 tasks. Increase the count as needed, e.g., loop = {1,2,3,4,5}; to fetch 500 tasks.

  38. for each i in loop

  39. {

  40. taskParameter = Map();

  41. taskParameter.put("index",indexValue);

  42. taskParameter.put("range",rangeValue);

  43. taskParameter.put("status","notcompleted");

  44. // info taskParameter;

  45. taskResponse = zoho.projects.getRecords(portalId,projectId,"tasks",taskParameter,0,"closealltasks");

  46. // info taskResponse;

  47. if(taskResponse.containKey("tasks"))

  48. {

  49. taskIds = list();

  50. for each task in taskResponse.get("tasks")

  51. {

  52. taskId = task.get("id");

  53. if(task.get("is_recurrence_set"))

  54. {

  55. updateTaskParameter = Map();

  56. updateTaskParameter.put("json_string",{"recurrence":{"recurring_frequency":"none","time_span":"1","number_of_occurrences":"2","is_comments_recurred":false,"recurrence_type":"after_current_task_completed"}});

  57. updateTaskResponse = zoho.projects.update(portalId,projectId,"tasks",taskId,updateTaskParameter,"closealltasks");

  58. info updateTaskResponse;

  59. }

  60. if(task.containsKey("dependency") && task.get("dependency").containsKey("predecessor"))

  61. {

  62. predTasks = task.get("dependency").get("predecessor");

  63. predList = list();

  64. for each predTaskId in predTasks

  65. {

  66. predList.add(task.get("dependency").get("dependencyDetails").get(predTaskId).get("IS_COMPLETED"));

  67. }

  68. if(!predList.contains(false))

  69. {

  70. taskIds.add(taskId);

  71. }

  72. }

  73. else

  74. {

  75. taskIds.add(taskId);

  76. }

  77. info "taskIds : " + taskIds;

  78. }

  79. bulkUpdateParams = Map();

  80. bulkUpdateParams.put("taskids",taskIds.toText().remove("[").remove("]"));

  81. bulkUpdateParams.put("status",{"id":statusId});

  82. info bulkUpdateParams;

  83. /* Bulk update */

  84. taskBulkUpdate = invokeurl

  85. [

  86. url :projectsv3APIEndPoint + "/portal/" + portalId + "/projects/" + projectId + "/tasks/bulk-update"

  87. type :PATCH

  88. parameters:bulkUpdateParams.toString()

  89. connection:"closealltasks"

  90. ];

  91. info taskBulkUpdate;

  92. }

  93. else

  94. {

  95. break;

  96. }

  97. }

  98. }

  99. return "success";

参数映射:

  1. portalId - Portal System ID

  2. projectId - Project System ID

保存自定义函数后,创建一个工作流程规则,并进行以下设置:

规则保存后,每当项目被标记为“已完成”时,所有未完成的任务都会自动完成。这确保项目能够准确反映其真实的完成状态,避免手动清理,并使您的项目保持最新状态。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 11:07:20

揭秘气候变化对农作物产量的影响:R语言数据分析全流程详解

第一章:农业产量的 R 语言气候影响分析 在现代农业研究中,理解气候变量对农作物产量的影响至关重要。R 语言作为一种强大的统计分析工具,能够高效处理气象与农业数据,揭示温度、降水、湿度等因子与作物产出之间的潜在关系。通过整…

作者头像 李华
网站建设 2026/6/9 23:49:58

【MLOps工程师必看】:用语义化Docker标签实现AI模型可追溯性

第一章:AI 模型版本的 Docker 标签管理在持续集成与交付(CI/CD)流程中,AI 模型的版本控制至关重要。Docker 镜像标签是标识不同模型版本的有效手段,合理使用标签可确保部署环境的一致性与可追溯性。语义化标签策略 采用…

作者头像 李华
网站建设 2026/6/9 13:09:28

FlutterOpenHarmony侧边栏抽屉组件开发

前言 侧边栏抽屉是移动应用中常见的导航模式,它将次要的导航选项和功能入口收纳在屏幕侧边,用户可以通过滑动或点击按钮来展开。在笔记应用中,侧边栏通常用于展示文件夹列表、标签分类、设置入口等内容。本文将详细介绍如何在Flutter和OpenHa…

作者头像 李华
网站建设 2026/6/9 19:48:40

FlutterOpenHarmony弹窗与对话框组件

前言 弹窗和对话框是应用中与用户进行交互的重要方式,它们用于显示提示信息、确认操作、收集用户输入等场景。在笔记应用中,删除确认、保存提示、表单输入等功能都需要使用弹窗组件。一个设计良好的弹窗应该清晰传达信息、提供明确的操作选项&#xff0c…

作者头像 李华
网站建设 2026/6/9 22:00:54

【数据科学必备技能】:用R和Python打通数据库的6种高效方法

第一章:R-Python 数据库交互概述在现代数据科学实践中,R 与 Python 作为两大主流分析语言,常需协同访问数据库以完成复杂的数据处理任务。通过标准化接口,两者均可连接主流数据库系统,如 PostgreSQL、MySQL 和 SQLite&…

作者头像 李华