Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

うちのRedmineの使い方(2)

2,916 views

Published on

redmine.tokyo 第16回勉強会。
非IT会社でRedmineをAWSに新規構築して全社利用した中で行った設定や運用など

Published in: Technology
  • Login to see the comments

うちのRedmineの使い方(2)

  1. 1. うちのRedmineの使い方(2) redmine.tokyo 第16回勉強会 2019年5月18日 @tKusukawa 1
  2. 2. 自己紹介: @tKusukawa くすかわと申します。redmine.tokyoのスタッフです。 2008年からRedmineを使い始めて10年余 その間、4つの企業の全てでRedmineの恩恵を享受 Redmineプラグイン: WorkTime,WikiListsを公開 第1回勉強会(2011)でLT「うちのRedmineの使い方」 2
  3. 3. うちのRedmineの使い方(2) 3 昨年、非IT会社に入社 →Redmineを新規導入して 全社利用している事例を共有します (お気づきの点を教えて頂けると幸いです) (ソフトウェアは多く使われるほど良いものになるので)
  4. 4. Redmine導入の背景 関東と関西に20店舗余120名余の会社 全社アンケートで     店舗と本部の関係に課題 (それってITの問題じゃなくない?) 4
  5. 5. 店舗と本部の関係に課題 → コミュニケーションツール    としてRedmineを提案 (本質的にはITの問題じゃないけどね) 5
  6. 6. Redmine導入の目論見1 6 オープンに耐える  コミュニケーションを   身につける (隠蔽体質は自覚症状がないまま    組織を蝕むので本当に怖い)
  7. 7. Redmine導入の目論見2 7 業務のステータスを     見える化して やり切る習慣を身につける (放置体質も超ヤバい)
  8. 8. 構築内容 インフラ: AWS EC2 t3.medium amazon-linux-ami/2018.03       (Unicorn(Apache)、MySQL) 添付保存: AWS S3 (S3プラグインを利用) テーマ: Farend funcy 8 Environment: Redmine version 3.4.6.stable.17598 Ruby version 2.4.4-p296 (2018-03-28) [x86_64-linux] Rails version 4.2.10 Environment production Database adapter Mysql2 SCM: Subversion 1.9.7 Git 2.14.5 Filesystem ← 文字コード: utf8mb4 ★
  9. 9. プラグイン 9 Redmine plugins: clipboard_image_paste 1.12 https://github.com/peclik/clipboard_image_paste.git custom_users_as_assignees 0.0.3 https://github.com/tkusukawa/custom_users_as_assignees. redmine_already_read 0.0.5 https://github.com/tkusukawa/redmine_already_read.git redmine_banner 0.1.2 https://github.com/akiko-pusu/redmine_banner.git redmine_ckeditor 1.1.5 https://github.com/a-ono/redmine_ckeditor.git redmine_default_custom_query 1.3.0 https://github.com/hidakatsuya/redmine_default_custom_q redmine_extended_watchers 1.0.5 https://github.com/tkusukawa/redmine_extended_watchers. redmine_issue_templates 0.2.0 https://github.com/akiko-pusu/redmine_issue_templates.g redmine_s3 0.0.3 git://github.com/ka8725/redmine_s3.git redmine_unc_autolink 0.0.1 https://github.com/preciousplum/redmine_unc_autolink.gi redmine_wiki_lists 0.0.9 https://github.com/tkusukawa/redmine_wiki_lists.git redmine_wiki_unc 0.0.3 https://github.com/naitoh/redmine_wiki_unc.git redmine_work_time 0.3.4 https://github.com/tkusukawa/redmine_work_time.git selectbox_autocompleter 1.1.5 https://github.com/heriet/redmine-selectbox-autocomplet sidebar_hide 0.0.1 https://github.com/rsilvestri/redmine-sidebar-hide.git view_customize 1.2.2 https://github.com/onozaty/redmine-view-customize.git
  10. 10. s3.yml 10 [ec2-user@redmine ~]$ cat /opt/redmine/config/s3.yml production: access_key_id: ******************** secret_access_key: **************************************** bucket: redmine-files.******.net folder: files endpoint: s3.ap-northeast-1.amazonaws.com secure: true private: true expires: proxy: false thumb_folder: thumb ↑リージョン指定が必要
  11. 11. 使い方はシンプルに あえてルールは厳密にせず、    おおらかに ↑ トレーサビリティが高いから、    自律改善できる (最初に細かく作り込むのはアンチパターン) 11
  12. 12. わかりにくい文言を変更 12 トラッカー → チケット種別 注記 → コメント 説明 → 本文 「チケット」は Redmineの代名詞なのでチケットのまま!
  13. 13. 記法:見たままエディタ CKEditorプラグインを利用 マークダウン記法は非エンジニアには辛かろう 最初に覚える事(知らないと出来ない事)を最小限に ※ 一部Wikiマクロが使えないなどデメリットも 13
  14. 14. 未読件数表示 14 https://github.com/tkusukawa/redmine_already_read にて https://github.com/ameya86/ 氏、https://github.com/codeout/氏の リポジトリをForkして拡張したものを利用しています。 未読
  15. 15. 担当者を複数化 15 複数部署や複数店舗に依頼や周知する場合に利用 https://github.com/tkusukawa/custom_users_as_assigneesにて https://github.com/preciousplum/氏のリポジトリをForkして一部修正
  16. 16. プロジェクトは基本1つ 16 PJ: 掲示板 [依頼、周知、会議録、…]   ├社員名簿   ├店舗情報   ├(メンバー限定 PJ)     ︙
  17. 17. チケット種別【依頼】 17 チケット起票者しかクローズできないようにした 投げっぱなしは悪。キャッチボールして下さい。 ちゃんと結果を返す。ちゃんと責任を持って終了。 起票者 担当者 新規 解決 終了(感謝) 起票者 対応者 新規 (やったよ) 終了(感謝)
  18. 18. チケット種別【周知】 18 完了連絡が不要な内容。チケットは新人も過去参照可 期限または最終更新から1週間で自動的にクローズ クローズ通知は要らないのでDB直でバッチ更新 [root@redmine scripts]# cat notif_over.rb #!/usr/bin/ruby # -*- coding: utf-8 -*- require 'mysql2' require_relative '_redmine_secrets' begin $mysql_redmine =Mysql2::Client.new( host: $db_host_redmine, port: $db_port_redmine, username: $db_username_redmine, password: $db_password_redmine, encoding: 'utf8', database: $db_database_redmine, ) # トラッカーが「8:周知」でステータスが「5:終了」以外で期日が設定されている # 且つ期日に到達しているチケット または # トラッカーが「8:周知」でステータスが「5:終了」以外で期日未設定 # 且つ更新から7日以上経っているチケットを抽出 $sql =<<-EOS select id, status_id from issues where tracker_id = 8 AND status_id != 5 AND ( (due_date is not null AND due_date <= NOW()) OR (due_date is null AND updated_on <= (NOW() - INTERVAL 7 DAY)) ) EOS results = $mysql_redmine.query($sql) $sql = nil results.each do |res| id = res['id'] status_id = res['status_id'] #puts id $sql = "UPDATE issues SET status_id = 5 WHERE id = #{id}" #puts $sql $mysql_redmine.query($sql) $sql = nil $sql =<<-EOS INSERT INTO journals ( journalized_id, journalized_type, user_id,created_on ) VALUES (#{id}, 'Issue', 1, NOW()); EOS $mysql_redmine.query($sql) $sql = nil journal_id = $mysql_redmine.last_id $sql =<<-EOS INSERT INTO journal_details (`journal_id`,`property`,`prop_key`,`old_value`,`value`) VALUES(#{journal_id},'attr','status_id',#{status_id},5); EOS #puts $sql $mysql_redmine.query($sql) $sql = nil end rescue => error puts "nERROR" puts error.to_s error.backtrace.each do |trace| puts trace end if $sql puts "nSQL:" puts $sql end exit 1 end
  19. 19. チケット種別【会議録】 19 せっかく会議しても決まったことが忘れ去られる → 議事録に決定とToDoを書いて回覧チェック 会議目的が不明だと知ったかぶりから空中戦になる → 予め目的、アジェンダ、資料をチケット化
  20. 20. 【会議録】雛形を IssueTemplateで自動適用 20
  21. 21. 【会議録】自動的に チケット本文を編集モード 21 <ViewCustomize> パスのパターン: /issues/[0-9]+ 挿入位置: 全てのページのヘッダ 種別: JavaScript コード: function showUpdateShowDescriptionEdit() { showAndScrollTo("update", "issue_notes"); $('#issue_description_and_toolbar').show(); $('#issue_description_and_toolbar').prev().hide(); } $(window).load(function () { setTimeout(function(){ switch($('#issue_tracker_id').val()) { // なぜか時間を置かないと取れない case "7": // 会議トラッカー showUpdateShowDescriptionEdit(); } },500); });
  22. 22. <ViewCustomize> パスのパターン: .*/issues/.* 挿入位置: 全てのページのヘッダ 種別: JavaScript コード: $(window).load(function () { setTimeout(function(){ $('#issue-form').submit(function(e) { if($('#issue_status_id').val() == 1) { return; } // ステータス=新規のときは動かない // 回覧確認者のテーブルを探索 $('#cke_1_contents > iframe').contents().find('th').each(function(i,e) { if( $(e).text().lastIndexOf('者') != -1 ) { // ex.対応者,確認者.. var col = this.cellIndex; $(this).parents('table').find('tr').each(function(i,e) { $(e).find('td').each(function(i,e) { if(this.cellIndex != col) { return; } // 対象カラム以外はスキップ var tbl_name = $(this).text().replace(/( | |さん|様|社長|副社長|部長|取締役|殿)/g, ''); if(tbl_name == '') { return; } tbl_next = $(this).next().text().replace(/s+/g, ''); // ユーザカスタムフィールドを探索 $('span.user_cf > label').each(function(i,e) { check_name = $(this).text().trim(); check_names = check_name.split(/s+/); check_names[check_names.length] = check_name.replace(/s+/g, ''); match = false; for(i = 0; i < check_names.length; i++) { check = check_names[i].replace(/( | |さん|様|社長|副社長|部長|取締役|殿)/g, ''); if(tbl_name == check) { match = true; break; } } 【会議録】回覧チェック表から 対応者を自動でON/OFF 22 if(match) { if(tbl_next == '') { $(this).find('input').prop('checked', true); } else { $(this).find('input').prop('checked', false); } } }); }); }); } }); }); },1000); });
  23. 23. 人員名簿 23 チケット一覧に顔写真 パスのパターン:.*/issues
 挿入位置: 全てのページのヘッダ
 種別: JavaScript
 コード:
 $(function() { $("[id^=issue-]").each(function(i,e) { var iid = $(e).attr("id").replace("issue-",""); var td = $(e).find('td.cf_9'); var attache_id = td.text(); td.text(""); td.append('<a href="/issues/'+iid+'"><img src="/attachments/thumbnail/'+attache_id+'" /></a>'); }); }); ←マクロ {{thumbnail(face.png)}} のリンクを確認してカスタムフィールド : faceに設定
  24. 24. 店舗情報 24 WikiListsプラグインで店舗の人員一覧を表示 {{ref_issues(-i=2,-f:cf_3 == [subject])}} -i=2 : カスタムクエリID=2 -f:cf_3 == [subject]: カスタムフィールド3「勤務地」がチケットの題名と同じチケットを抽出
  25. 25. $(function(){ // divタグのclassにcf_3:勤務地かcf_10:貸与先を含むものを見つけて内容をリンクに書き換え(チケット詳細) $("div.cf_3,div.cf_10").each(function(i,e){ var div = $(e).find('div.value'); var text = div.text() div.html('<a href="#" onclick="officeMemberRedirect(''+text+'');return false;">'+text+'</a>' ); }); // tdタグのclassにcf_3:勤務地かcf_10:貸与先を含むものを見つけて内容をリンクに書き換え(チケット一覧) $("td.cf_3,td.cf_10").each(function(i,e){ var text = $(e).text() $(e).html('<a href="#" onclick="officeMemberRedirect(''+text+'');return false;">'+text+'</a>' ); }); // aタグのclassにuserを含むものを見つけて関数呼び出しに書き換え $("a.user").each(function(i,e){ var name = $(e).text(); $(e).attr("onclick", "return officeMemberRedirect('"+name+"');"); }); }); パスのパターン:.*
 挿入位置: 全てのページのヘッダ
 種別: JavaScript
 コード:
 function officeMemberRedirect(name) { //チケットIDのオートコンプリートのAJAXを使ってチケットの題名をIDに変換してリダイレクト //console.log('officeMemberRedirect: '+ name); $.getJSON('/issues/auto_complete', {project_id: "office", term: name}) .done( function(data) { var id = null; $.each(data, function(index, elem) { // 最初にみつかったチケットにリダイレクト var href = "/issues/"+elem["id"]; location.href = href; return false; }); }); //チケットIDのオートコンプリートのAJAXを使ってチケットの題名をIDに変換してリダイレクト $.getJSON('/issues/auto_complete', {project_id: "member-mng", term: name.replace(" "," ")}) // 全角スペース検索 .done( function(data) { $.each(data, function(index, elem) { // 最初にみつかったチケットにリダイレクト var href = "/issues/"+elem["id"]; location.href = href; return false; }); }); $.getJSON('/issues/auto_complete', {project_id: "member-mng", term: name}) // 上記で無ければ半角スペースで検索 .done( function(data) { $.each(data, function(index, elem) { // 最初にみつかったチケットにリダイレクト var href = "/issues/"+elem["id"]; location.href = href; return false; }); }); return true; } 人員名簿/店舗情報へのリンク 25 チケット選択サジェストのAjax を使ってチケットへリダイレクト
  26. 26. 夜間バッチで自動化 26 ● 「グループ」「人員チケットの部署/店舗」 「メーリングリスト」の矛盾をチェック (スクリプトからDB直アクセス) ● メーリングリストをWikiに自動反映 DB直アクセスで更新有無をチェックして REST APIでWiki更新
  27. 27. まとめ 27 非IT企業にRedmineをコミュツールとして導入 企業文化(業務習慣)の健全化が目的 → 組織の成熟度を上げて給料の高い会社にしたい ・チケット運用方法(依頼のキャッチボール) ・ViewCustomize等による作り込み ・人員情報と店舗情報による顔の見える化 などを共有させて頂きました。

×