ルールでセクションを作成

プロジェクトをセクションでタスク分類しているのですが、セクションの作成を自動化したいです。

例えば下記のような構成で、2)に新規タスクが追加されたとき、1)にセクションを追加したいです。

  1. 顧客サポートプロジェクト:顧客名でセクション分類
  2. 顧客一覧プロジェクト:タスク名=顧客名

現状、Advancedプランではできそうにないのですが、AIとか利用すると実現できたりするのでしょうか。

2 Likes

@nctakuwa さん、こんにちは

ご要望の件、試してみました。
1)AI-Studio でルールを作成

2)ルールーの実行結果
セクションを作成することは出来ないそうです。

1 Like

ありがとうございます。なんと素早い!
自動化できると便利なのですが、やっぱり手動操作するしかないのですね。

1 Like

素朴な疑問ですが、
顧客名は、自動でセクションを作成するほど、頻繁に新しい顧客が出てくるのでしょうか?
顧客が毎日の様に、新規なのでしょうか?
仮に、顧客サポートプロジェクトの方を、セクションで分けずに、カスタムフィールドでグループ化で良ければ、違った対応も可能かと。
参考:🪄 Design magical tabs with group, sort, and filter!


セクションの件は、こういう話もありますね。


追記:スクリプトでセクションが作れるかもです。

Script Actions

情報ありがとうございます。
一般社員によるフォームからの登録だけで関連するところに漏れなく反映できるようにしたいという意図です。
カスタムフィールドの項目追加にしても少し特殊な操作になる(どちらにしても別のプロジェクトでの操作になる)ので、管理者的なユーザが行うことになってしまいます。

1 Like

もし顧客名を事前にリストアップ出来るのであればこんな方法もあります。

「顧客一覧プロジェクト」 マルチホームするルールを作る

「顧客サポートプロジェクト」 カスタムフィールド「顧客名」を単一選択で作っておく

「顧客一覧プロジェクト」 タスク名から近い顧客名をAIに選ばせる

「顧客サポートプロジェクト」 はボードビューにしてグループをセクションからカスタムフィールド「顧客名」にする

顧客名を事前に単一選択(リスト)で登録しておく手間はあります。
これは、テキスト形式のカスタムフィールドだとグループ化出来なかったからです。
(もしかしたらタスク名をAIで単一選択項目に追加する事が出来るかも。未確認)

1 Like

@nctakuwa @Takeshi_Yamazaki1 さん

少しお聞きしたいのですが

1) 顧客一覧プロジェクト:タスク名=顧客名

  • これは、いわゆる顧客リストと考えていいですか?
  • イメージとしては、A社、B社、C社・・・
    – もしかしたら、 A社東京、A社大阪、A社福岡・・・ かな

2) 顧客サポートプロジェクト:顧客名でセクション分類

  • 顧客とのやり取りを、管理するのでしょうか?
  • 顧客とのやり取りのイメージは、A社・問合せ1、A社・問合せ2、A社・問合せ3・・・ ?

これって、CRMみたいな仕組みをお考えなのでしょうか?
こんな感じですか?

色々と情報をいただきありがとうございます。
ご提示のとおり、CRM的な運用でサポート対応なども一つのプロジェクトにすべてマルチホームで紐づけて、顧客ごとに一覧化したいというものです(都度検索すればよい話ではあるのですが)。
リンクの動画、後で確認させていただきます。

1 Like

サンプルですが、
こんな感じで、AIを使うことで別プロジェクトの情報をコピペ出来ました。

1)ルール


AIへのガイダンス
「 あなたはこのルールを実行するAIアシスタントです。
タスクのカスタムフィールドp1を確認してください。
T-0-1-2内で、カスタムフィールドp1と同じ名前のタスクを検索してください。
同じ名前のタスクが見つかった場合は、その見つかったタスクのカスタムフィールド「text0-1-2」の値を取得し、カスタムフィールドtext1に入力します。同じ名前のタスクが見つからない場合、または「text0-1-2」の値を取得できない場合は、その旨をコメントしてください。」

2)ルールを持つプロジェクト 0-1-1

3)参照先のプロジェクト 0-1-2

link: Copy and Paste Text from Another Project Using AI-Studio


AIの代わりに、スクリプトで実行できそうです。
途中までできたけど、エラーで動きません。

// 環境変数からトークンを取得するか、より安全な方法で管理することを推奨
const ASANA_TOKEN = process.env.ASANA_TOKEN || ‘Bearer YOUR_PERSONAL_ACCESS_TOKEN’;
// 処理対象のタスクID(実行時に指定する)
const ORIGINAL_TASK_ID = process.env.TASK_ID || ‘ORIGINAL_TASK_ID’;

// T-0-1-1のIDを設定
const PROJECT_ID = ‘1210933114705490’;

const axios = require(‘axios’);

const headers = {
Authorization: ASANA_TOKEN
};

// ヘルパー関数: タスクの詳細を取得
async function getTask(taskId) {
const res = await axios.get(https://app.asana.com/api/1.0/tasks/${taskId}, {
headers,
params: {
opt_fields: ‘name,custom_fields,custom_fields.name,custom_fields.text_value,workspace.gid’
}
});
return res.data.data;
}

// ヘルパー関数: タスク検索
async function searchTasks(workspaceId, searchText) {
const res = await axios.get(https://app.asana.com/api/1.0/workspaces/${workspaceId}/tasks/search, {
headers,
params: {
text: searchText,
projects: PROJECT_ID,
opt_fields: ‘name,gid’
}
});
return res.data.data;
}

// ヘルパー関数: タスクにコメント追加
async function commentOnTask(taskId, message) {
try {
await axios.post(https://app.asana.com/api/1.0/tasks/${taskId}/stories, {
text: message
}, { headers });
console.log(コメント追加成功: ${message});
} catch (error) {
console.error(コメント追加失敗: ${error.message});
throw error; // エラーを上位に伝播させる
}
}

// メイン処理
async function main() {
try {
console.log(処理開始: タスク ${ORIGINAL_TASK_ID});

// 元のタスクを取得し、カスタムフィールドp1の値を抽出
const originalTask = await getTask(ORIGINAL_TASK_ID);
const p1Field = originalTask.custom_fields.find(f => f.name === 'p1');
const p1 = p1Field?.text_value;
const workspaceId = originalTask.workspace.gid;

if (!p1) {
  await commentOnTask(ORIGINAL_TASK_ID, 'カスタムフィールドp1の値が取得できませんでした。');
  return;
}

console.log(`p1の値: ${p1}`);

// 検索APIを使用してタスクを検索
const searchResults = await searchTasks(workspaceId, p1);
const matchedTask = searchResults.find(task => task.name === p1);

if (!matchedTask) {
  await commentOnTask(ORIGINAL_TASK_ID, `[T-0-1-1](Project:1210933114705490)内に「${p1}」という名前のタスクが見つかりませんでした。`);
  return;
}

console.log(`一致するタスクを発見: ${matchedTask.gid}`);

// 一致したタスクの詳細を取得
const taskDetails = await getTask(matchedTask.gid);

// 一致したタスクの名前を取得して元のタスクのtext1に設定
const taskName = taskDetails.name;

// カスタムフィールドIDを取得
const text1Field = originalTask.custom_fields.find(f => f.name === 'text1');
if (!text1Field) {
  await commentOnTask(ORIGINAL_TASK_ID, 'カスタムフィールドtext1が見つかりませんでした。');
  return;
}

// 元のタスクのtext1に値を設定
const customFields = {};
customFields[text1Field.gid] = taskName;

await axios.put(`https://app.asana.com/api/1.0/tasks/${ORIGINAL_TASK_ID}`, {
  custom_fields: customFields
}, { headers });

await commentOnTask(ORIGINAL_TASK_ID, `カスタムフィールドtext1に「${taskName}」を設定しました。`);
console.log('処理完了');

} catch (error) {
console.error(エラーが発生しました: ${error.message});
try {
await commentOnTask(ORIGINAL_TASK_ID, エラーが発生しました: ${error.message});
} catch (commentError) {
console.error(‘コメント追加中にエラーが発生しました:’, commentError.message);
}
}
}

// スクリプトを実行
main().catch(error => {
console.error(‘予期せぬエラーが発生しました:’, error);
process.exit(1);
});

色々と試していただきありがとうございます!
Advancedではスクリプトを利用できないので、AIの方を少し深堀りしてみます。

1 Like

そうなんですか
AI-Studio使うと、クレジット消費するので気をつけてください。
スクリプトは使えないのでしょうか?
こちら Asana の料金| Personal、Starter、Advanced、2 つの Enterprise プラン • Asanaでは、わからないですね。

こちらの記述ですと、「Script actions are available to Enterprise and Enterprise+ customers.」ですね。
Script Actions

少し調べたのですが、スクリプトはEnterprise以上ですがAPIの方は他のプランでも利用できるようです。
WebHookでイベントを受信し、そこでセクション作成したり結構何でもできるようです。
そこまでやるかどうか・・・検討したいと思います。

1 Like