Redmineカスタマイズ:作業依頼トラッカーの開発
自己紹介
三菱UFJインフォメーションテクノロジー株式会社の中島崇と申します。
GitLabやSonatype Nexus Repositoryなど、世の中ではよく使われているデファクトツールに関して、社内への導入検討、導入済ツールのレベルアップ、ガイディング等を行っています。
また、昨年度は、Redmineの社内ハンズオン研修の講師をしていました。
背景
当社には、さまざまな部署があり、部署間の作業依頼を管理するシステム的な仕組みは整っていました。
しかし、その依頼を部署内の各システム担当者やラインメンバーに振り分けて管理する仕組みが整っておらず、多くの場合はExcelで管理していました。
主な問題点
Excelによる管理は機能していましたが、次のような問題がありました。
- Excel管理簿のファイルが破損。いつの間にかバックアップから復元されて更新したはずの内容が消失。
- Excel管理簿をフィルタリングしたまま更新した結果、意図しない別セルを誤更新。
- Excel管理簿では、対応状況の詳細を把握できない。
- 対応履歴の追跡が困難。
Redmineによる管理高度化
これらの問題解消を目的に、社内に導入済のRedmineを活用することにしました。
1件の作業依頼に対して、部署内の各システム/所属ラインごとに対応を管理する必要があるため、1つの作業依頼チケットの配下に、システム/所属ライン単位で複数の子チケットを作成して管理する方針で検討しました。
この運用は、既存のトラッカー(Redmineのチケット種別)でも実現可能でしたが、視認性やチケット作成のコストを考慮し、作業依頼[TaskRequest]
という専用トラッカーを新設することにしました。
※図は当社にて作成
要件定義
作業依頼トラッカーの要件は、次の通りにしました。
- 作業依頼チケット(親)の配下に、各システム/所属ライン単位の子チケットを簡単に作れること。
- 作業依頼チケット(親)の説明欄(依頼内容)、関連URLリンクを子チケットからも簡単に確認ができること。
- 子チケットの対応結果を作業依頼チケット(親)から簡単に確認ができること。
設計、実装
前提
当社で利用しているRedmineのバージョン、プラグインの一部です。
他にも様々なプラグインを導入しているため、安定稼働を考慮して、以下のバージョンを利用しています。
- Redmine version:4.2.2.stable
- Computed custom field : 1.0.7
- Redmine Custom Workflow plugin : 2.0.7
- View Customize plugin : 2.8.1
ステータス遷移
他の既存トラッカーを参考に、次のように設定しました。
カスタムフィールド
次の3つの項目を新設して、作業依頼トラッカーに適用しました。
また、各項目にはComputed_custom_fieldプラグインによりそれぞれ下記の計算式を埋め込み、導出属性として機能するようにしました。
※他にも適用した項目はありますが、既に存在していたため割愛します。
- ルートチケット番号
ルートチケット(階層構造の最上位の作業依頼トラッカー)のチケット番号を自動的に表示する項目
if self.parent_id.present? then
if self.tracker_id == self.parent.tracker_id then
"#{self.parent.custom_field_value(101)}" # ルートチケット番号(101)
else
"#{self.id}"
end
else
"#{self.id}"
end
- 作業依頼内容(ルートチケット説明欄)
ルートチケットの説明欄(依頼内容)を、配下の子チケットに自動的に表示する項目
if self.parent.present?
if self.id == self.custom_field_value(101) # ルートチケット番号(101)
""
else
"{{ref_issues(-f:id = #{self.custom_field_value(101)}, -t=description)}}"
end
else
""
end
- 作業結果一覧(子チケット回答欄)
子チケットの回答欄や最新コメントを自動的に一覧表示する項目
"{{ref_issues(-p, -0, -f:parent_id = #{self.id}, status, subject, assigned_to, cf_102, cf_103,last_notes)}}" # 回答日(102)、回答者(103)
Custom workflows
ワークフローには、次のフック処理を入れました。
- 親チケットのリンク項目の内容を子チケットに継承する
if (@issue.tracker_id == 101) then # 作業依頼トラッカー(101)
if (@issue.parent.present?)
if (@issue.parent.tracker_id == 101) && (@issue.parent.custom_field_value(104).present?) # リンク(104)
link = @issue.parent.custom_field_value(104)
@issue.custom_field_values = {'104' => link }
end
end
end
- 進捗率100%(全ての子チケット終了)で終了待ステータスに自動更新する
if (@issue.tracker_id == 101) # 作業依頼トラッカー(101)
if @issue.done_ratio_changed?
if (@issue.done_ratio == 100) && (!@issue.closed?)
@issue.status_id = 20 # 終了待ステータス(20)
end
end
end
表示/編集画面のカスタマイズ(抜粋)
- 作業依頼トラッカー上に、子チケット作成ボタンを追加
if(trackerId == '101') {
/* 子チケット作成ボタン */
let link_url1=$("div#issue_tree a:first").attr('href')+"&issue%5Btracker_id%5D=101";
let link_title1="作業依頼チケット作成"
let link1 = $('<a title="' + link_title1 + '" class="icon icon-add" href="' + link_url1 + '">' + link_title1 + '</a>');
$("div#issue_tree").append(
$('<p>').append($('<strong>').text("【子チケット新規登録】")),
$('<div>', { style: 'width:33%;height:2em;float:left' }).append(link1),
);
};
※視認性向上のため、各項目のグルーピングや並び順もカスタマイズしていますが、ここでは割愛します。
サンプル
ルートチケット
子チケット
導入結果と効果
スモールスタートで、私が所属するラインで限定的に作業依頼トラッカーを運用した結果と効果です。
- ファイル破損やデータ消失のリスクがなくなり、変更履歴も追跡可能。
- 誰が、何を、いつまでに対応する必要があるのか、また現在の対応状況が明確化。
- チケット一覧を期日順でソート表示することで、期日管理や担当者へのフォローもしやすく、期限切れや対応漏れが大幅に減少。
導入後の課題
導入により、以下の課題も見えてきました。
- 導出項目のカスタムフィールドを適用するなどの工夫をしたが、チケット作成は依然として手作業で行う必要があるため、負荷がかかる。
- チケットの期日管理においては、担当者がプロアクティブにチケット一覧を確認する必要がある。
今後の展望
今後はこれらの課題解消を目指し、以下の活動を行っていきたい所存です。
- API連携やAIエージェントなどの活用により、チケット作成や期限切れチケットのフォローの負荷軽減/自動化。
- 作業依頼トラッカーの社内活用事例を増やし、社内での認知度向上と利用者の拡大。
最後に
なお、掲載したソースコードはサンプルになります。本ソースコードを使用することで発生するいかなる損害や不利益について、当社は一切の責任を負いませんので自己の責任においてご利用ください。
Discussion