Script Action to automatically make a task as subtask of a parent task.

I tried multiple ways to see if this is possible but not sure if it is as design, I have am able to able to retrieve the parent task ID and link it with the new task that is created but I am not able to make that new task as a subtask to the parent task.

Has anyone tried this or managed to achieve some thing like this?

If you set the Parent property when creating the task, it should work. What specifically have you tried and what error(s), if any, are you getting?

Sure, here is the code

const run = async () => {
  try {
    if (!task_gid) {
      throw new Error('task_gid is undefined.');
    }

    log(`Processing form submission: ${task_gid}`);

    // Get form task details
    const formTask = await tasksApiInstance.getTask(task_gid, { 
      opt_fields: 'name,notes,custom_fields' 
    });
    
    // Extract the parent task ID from the notes
    let parentTaskId = null;
    
    if (formTask.data.notes) {
      const patterns = [
        /[Pp]arent\s*[Tt]ask\s*ID\s*:?\s*(\d+)/,
        /[Tt]ask\s*ID\s*:?\s*(\d+)/,
        /[Pp]arent\s*ID\s*:?\s*(\d+)/,
        /ID\s*:?\s*(\d+)/
      ];
      
      for (const pattern of patterns) {
        const match = formTask.data.notes.match(pattern);
        if (match && match[1]) {
          parentTaskId = match[1];
          log(`Extracted parent task ID from notes: ${parentTaskId}`);
          break;
        }
      }
    }
    
    if (!parentTaskId) {
      log("No parent task ID found in form submission");
      return;
    }
    
    // Get the parent task with its subtasks and assignee
    log(`Looking up parent task: ${parentTaskId}`);
    try {
      const parentTask = await tasksApiInstance.getTask(parentTaskId, { 
        opt_fields: 'name,subtasks.name,subtasks.gid,assignee' 
      });
      
      const parentTaskName = parentTask.data.name;
      log(`Found parent task: "${parentTaskName}"`);
      
      // Get parent task assignee if available
      const parentTaskAssignee = parentTask.data.assignee ? parentTask.data.assignee.gid : null;
      if (parentTaskAssignee) {
        log(`Parent task assignee: ${parentTaskAssignee}`);
      } else {
        log('Parent task has no assignee');
      }
      
      // Find the "Config Checklist" subtask
      let configSubtaskGid = null;
      let configSubtaskName = null;
      
      if (parentTask.data.subtasks && parentTask.data.subtasks.length > 0) {
        for (const subtask of parentTask.data.subtasks) {
          if (subtask.name.startsWith("Config Checklist:")) {
            configSubtaskGid = subtask.gid;
            configSubtaskName = subtask.name;
            log(`Found Config Checklist subtask: "${configSubtaskName}"`);
            break;
          }
        }
        
        if (!configSubtaskGid) {
          for (const subtask of parentTask.data.subtasks) {
            if (subtask.name.includes("Config Checklist")) {
              configSubtaskGid = subtask.gid;
              configSubtaskName = subtask.name;
              log(`Found Config Checklist subtask: "${configSubtaskName}"`);
              break;
            }
          }
        }
      }
      
      if (!configSubtaskGid) {
        log("No Config Checklist subtask found in parent task!");
        return;
      }
      
      // Create a summary of the form submission
      let formSummary = "### Form Submission Summary\n\n";
      formSummary += "**Submitted On:** " + new Date().toLocaleDateString() + "\n\n";
      
      // Extract form data from task notes
      let formDetails = formTask.data.notes.replace(/Parent Task ID:.*?\n+/i, '');
      formDetails = formDetails.replace(/<web>[\s\S]*?<\/web>/g, '');
      
      formSummary += "**Form Details:**\n" + formDetails + "\n";
      formSummary += "\nView original form submission: https://app.asana.com/0/" + task_gid + "\n";
      
      // Add the comment to the Config Checklist subtask
      log(`Adding form summary comment to subtask "${configSubtaskName}"...`);
      const commentBody = {
        data: {
          text: formSummary
        }
      };
      
      // CORRECT ORDER: body first, then task_gid
      const commentResponse = await storiesApiInstance.createStoryForTask(commentBody, configSubtaskGid);
      log('Comment added successfully to Config Checklist subtask!');
      
      // Add a comment to the form task with link to parent task
      const formTaskCommentBody = {
        data: {
          text: "This form submission is for task: https://app.asana.com/0/" + parentTaskId + "\n\nForm data has been added as a comment to the Config Checklist subtask."
        }
      };
      
      await storiesApiInstance.createStoryForTask(formTaskCommentBody, task_gid);
      log('Added reference comment to form submission task');
      
      // Try to convert form task to a subtask of the parent task
      try {
        // Update name, assignee, and parent in one call
        const makeSubtaskBody = {
          data: {
            name: "CC: " + parentTaskName,
            parent: parentTaskId
          }
        };
        
        // Add assignee if available
        if (parentTaskAssignee) {
          makeSubtaskBody.data.assignee = parentTaskAssignee;
        }
        
        // Attempt to set parent and update other fields
        await tasksApiInstance.updateTask(makeSubtaskBody, task_gid);
        log(`Converted form submission to subtask of parent task and updated name/assignee`);
      } catch (subtaskError) {
        log(`Error converting task to subtask: ${subtaskError.message}`);
        
        // If making it a subtask fails, still update name and assignee
        try {
          const updateNameBody = {
            data: {
              name: "CC: " + parentTaskName
            }
          };
          
          if (parentTaskAssignee) {
            updateNameBody.data.assignee = parentTaskAssignee;
          }
          
          await tasksApiInstance.updateTask(updateNameBody, task_gid);
          log(`Updated form submission task name but couldn't make it a subtask`);
          if (parentTaskAssignee) {
            log(`Set assignee on form submission task to match parent task`);
          }
        } catch (nameError) {
          log(`Error updating task name: ${nameError.message}`);
        }
      }
      
      // Mark the form submission task as complete
      const completeFormTask = {
        data: {
          completed: true
        }
      };
      
      await tasksApiInstance.updateTask(completeFormTask, task_gid);
      log('Form submission task marked as complete');
      
      log('Form processing completed successfully!');
      
    } catch (taskError) {
      log(`Error processing parent task: ${taskError.message}`);
      if (taskError.stack) log(`Stack: ${taskError.stack}`);
    }

  } catch (error) {
    log(`Error: ${error.message}`);
    if (error.stack) log(`Stack: ${error.stack}`);
  }
};

run();

here is the log

Processing form submission: 1210580108940224
Extracted parent task ID from notes: 1210579117968273
Looking up parent task: 1210579117968273
Found parent task: "Task 123"
Parent task assignee: 1202373716269447
Found Config Checklist subtask: "Config Checklist: Task 123"
Adding form summary comment to subtask "Config Checklist: Task 123"...
Comment added successfully to Config Checklist subtask!
Added reference comment to form submission task
Error converting task to subtask: Bad Request
Updated form submission task name but couldn't make it a subtask
Set assignee on form submission task to match parent task
Form submission task marked as complete
Form processing completed successfully!
Finished in 4524 ms.

Thanks for looking through.

Ah OK - as I mentioned above, the way to do it is to set the parent when creating the task.

As it says in the docs, you can’t do it afterward via a PUT (i.e. an update); if you want to do it afterward, you have to use the separate setParent endpoint:

1 Like

Hey thanks, can you link to the page where you are seeing this?

Not code savvy so looking for some help to change the current code or would have to read up on the link you provide.

I think this one helped

Yes, you got it!

Sorry, I should have provided the URLs for you above.

FYI here is the page where I quoted the above highlighted text from. And you found the page for the call to set a task’s parent.