2月 14th, 2009at 12:18
Tags: Redmine, Ruby on Rails
Redmineプラグイン開発 – 日付指定で時間コストを表示
- NetBeans6.5で作ります。
- ソースはGoogle Codeを参照のこと。
- redmineは「c:\fujihara\Ruby\redmine-0.8.0」にあって、WEBrickを使って動かす。
ValueObject
表示用データを格納するValueObjectをplugin_root/app/libに作成。
Main
# To change this template, choose Tools | Templates # and open the template in the editor. class TimeReportMainVO TRACKER_SUM_STRING = "合計" def initialize @project_name = "" #FIXME @trackers = Hash.new() all_trackers = Tracker.find(:all) all_trackers.each do |tracker| @trackers[tracker.name] = TimeReportDetailVO.new() end @trackers[TRACKER_SUM_STRING] = TimeReportDetailVO.new() end def get_tracker(name) return trackers[name] end def put_tracker(name, value) trackers[name] = value end attr_accessor :project_name, :trackers end
Main has Detailになっている。
Detail
# To change this template, choose Tools | Templates # and open the template in the editor. class TimeReportDetailVO def initialize @estimated_hours = 0.0 @actual_performances = 0.0 @percentages = 0.0 end attr_accessor :estimated_hours, :actual_performances, :percentages end
Controller
ControllerではVOに計算したデータを格納する。
daizu_time_report_controller.rb
require 'logger'
require 'time_report_detail_v_o'
require 'time_report_main_v_o'
class DaizuTimeReportController < ApplicationController
before_filter :init
TRACKER_SUM_STRING = "合計"
def index
if @project_id && @start_date && @due_date
# counting per tracker.
# counting estimated_hours and time_entries and percentages.
@results = []
if @project_id == "all"
@projects.each do |project|
calc_per_project(project)
end
all_sumvo = calc_allsum(@results)
@results.push(all_sumvo)
else
project = Project.find(:first, :conditions => ["id = ?", @project_id])
calc_per_project(project)
end
end
end
def calc_per_project(project)
# per project.
mainvo = TimeReportMainVO.new()
mainvo.project_name = project.name
issues =
Issue.find(:all,
:conditions => ["start_date >= ? and due_date <= ? and project_id = ?",
@start_date, @due_date, project.id])
mainvo = count_per_tracker(issues, mainvo)
mainvo = calc_percentages(mainvo)
@results.push(mainvo)
end
def count_per_tracker(issues, mainvo)
sumvo = mainvo.get_tracker(TRACKER_SUM_STRING)
# counting per project and per tracker.
issues.each do |issue|
tracker_name = @trakcer_names[issue.tracker_id]
detailvo = mainvo.get_tracker(tracker_name)
# counting estimated_hours.
detailvo.estimated_hours += issue.estimated_hours
sumvo.estimated_hours += issue.estimated_hours
# counting time_entries.
time_entry = TimeEntry.find(:all, :conditions => ["issue_id = ?", issue.id])
time_entry.each do |entry|
detailvo.actual_performances += entry.hours
sumvo.actual_performances += entry.hours
end
mainvo.put_tracker(tracker_name, detailvo)
end
mainvo.put_tracker(TRACKER_SUM_STRING, sumvo)
return mainvo
end
def calc_percentages(mainvo)
mainvo.trackers.each do |key, detailvo|
detailvo.percentages =
calc_percentage(detailvo.estimated_hours, detailvo.actual_performances)
mainvo.put_tracker(key, detailvo)
end
return mainvo
end
def calc_percentage(estimated_hours, actual_performances)
if estimated_hours != 0 && actual_performances != 0
percentage =
(actual_performances / estimated_hours) * 100
percentage = percentage * 100
percentage = percentage.round
percentage = percentage / 100
return percentage
else
return 0.0
end
end
def calc_allsum(results)
sumvo = TimeReportMainVO.new()
sumvo.project_name = TRACKER_SUM_STRING
results.each do |result|
result.trackers.each do |tracker_name, detailvo|
detailsumvo = sumvo.get_tracker(tracker_name)
detailsumvo.estimated_hours += detailvo.estimated_hours
detailsumvo.actual_performances += detailvo.actual_performances
sumvo.put_tracker(tracker_name, detailsumvo)
end
end
sumvo.trackers.each do |tracker_name, tracker|
detailsumvo = sumvo.get_tracker(tracker_name)
detailsumvo.percentages =
calc_percentage(detailsumvo.estimated_hours, detailsumvo.actual_performances)
end
return sumvo
end
def init
@log = Logger.new(STDOUT)
@log.level = Logger::DEBUG
@project_id = params[:project_id]
@start_date = params[:start_date]
@due_date = params[:due_date]
@projects = Project.find :all
@trackers = Tracker.find(:all)
@trackers.push(Tracker.new(:name => TRACKER_SUM_STRING))
@trakcer_names = {}
@trackers.each do |tracker|
@trakcer_names[tracker.id] = tracker.name
end
end
end
View
グラフで表示するためにHTML5.JPのライブラリを利用。
plugin_root/app/assets/javascripts/html5jpにライブラリを配置した。
<script src="/javascripts/calendar/calendar.js" type="text/javascript"></script>
<script src="/javascripts/calendar/lang/calendar-ja.js" type="text/javascript"></script>
<script src="/javascripts/calendar/calendar-setup.js" type="text/javascript"></script>
<link href="/stylesheets/calendar.css" media="screen" rel="stylesheet" type="text/css" />
<h2><%= link_to h('大豆トップページ'), :controller => 'daizu_main', :action => 'index' %> > タイムレポート</h2>
<% form_tag({ :controller => 'daizu_time_report', :action => 'index' }, :id => 'query_form') do %>
<p><label for="project_id">プロジェクト</label>
<select name="project_id">
<option value="all">全てのプロジェクト</option>
<% @projects.each do |project| %>
<option value="<%= project.id %>"><%= project.name %></option>
<% end %>
</select>
<p><label for="issue_start_date">開始日</label>
<input id="issue_start_date" name="start_date" size="15" type="text" value="<%= params[:start_date] %>" />
<img alt="Calendar" class="calendar-trigger" id="issue_start_date_trigger" src="/images/calendar.png" />
<script type="text/javascript">
//<![CDATA[
Calendar.setup({inputField : 'issue_start_date', ifFormat : '%Y-%m-%d', button : 'issue_start_date_trigger' });
//]]>
</script></p>
<p><label for="issue_due_date">期限日</label>
<input id="issue_due_date" name="due_date" size="15" type="text" value="<%= params[:due_date] %>" />
<img alt="Calendar" class="calendar-trigger" id="issue_due_date_trigger" src="/images/calendar.png" />
<script type="text/javascript">
//<![CDATA[
Calendar.setup({inputField : 'issue_due_date', ifFormat : '%Y-%m-%d', button : 'issue_due_date_trigger' });
//]]>
</script></p>
<button type="submit">GO</button>
<% end %>
<% if @results %>
<p>[from:<%= params[:start_date] %> to:<%= params[:due_date] %>] のタイムレポート。</p>
<table class="list">
<tr>
<th></th>
<% @trackers.each do |tracker| %>
<th colspan="3" ><%= tracker.name %></th>
<% end %>
</tr>
<tr>
<th></th>
<% @trackers.each do |tracker| %>
<th>予想</th>
<th>実績</th>
<th>進捗</th>
<% end %>
</tr>
<% @results.each do |result| %>
<tr>
<th><%= result.project_name %></th>
<% @trackers.each do |tracker| %>
<td><%= result.get_tracker(tracker.name).estimated_hours %></td>
<td><%= result.get_tracker(tracker.name).actual_performances %></td>
<td>
<table class="progress" style="width: 40px;">
<tr>
<% if result.get_tracker(tracker.name).percentages == 0 %>
<td class="todo" style="width:100%;"></td>
<% elsif result.get_tracker(tracker.name).percentages == 100 %>
<td class="closed" style="width:100%;"></td>
<% elsif result.get_tracker(tracker.name).percentages > 100 %>
<td style="width:100%;background-color:red;"></td>
<% else %>
<td class="closed" style="<%= "width:" + result.get_tracker(tracker.name).percentages.to_s + "%;" %>"></td>
<td class="todo" style="<%= "width:" + (100 - result.get_tracker(tracker.name).percentages).to_s + "%;" %>"></td>
<% end %>
</tr>
</table>
<p class="pourcent"><%= result.get_tracker(tracker.name).percentages.to_s %>%</p>
</td>
<% end %>
</tr>
<% end %>
</table>
<% if params[:project_id] != "all" %>
<% @results.each do |result| %>
<h3><%= result.project_name %>の統計情報</h3>
<!--[if IE]><script src="/plugin_assets/redmine_daizu/javascripts/html5jp/excanvas/excanvas.js" type="text/javascript"></script><![endif]-->
<script src="/plugin_assets/redmine_daizu/javascripts/html5jp/graph/circle.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
var cg = new html5jp.graph.circle("yosou");
if( ! cg ) { return; }
var items = [
<% @trackers.each do |tracker| %>
<% if tracker.name != "合計" %>
<% if result.get_tracker(tracker.name).actual_performances != 0.0 %>
["<%=tracker.name%>", <%= result.get_tracker(tracker.name).actual_performances %>],
<% end %>
<% end %>
<% end %>
];
cg.draw(items);
var cg = new html5jp.graph.circle("jisseki");
if( ! cg ) { return; }
var items = [
<% @trackers.each do |tracker| %>
<% if tracker.name != "合計" %>
<% if result.get_tracker(tracker.name).estimated_hours != 0.0 %>
["<%=tracker.name%>", <%= result.get_tracker(tracker.name).estimated_hours %>],
<% end %>
<% end %>
<% end %>
];
cg.draw(items);
};
</script>
<table>
<tr>
<td>
<h4>予想</h4>
<div>
<canvas width="300" height="200" id="yosou"></canvas>
</div>
</td>
<td>
<h4>実績</h4>
<div>
<canvas width="300" height="200" id="jisseki"></canvas>
</div>
</td>
</tr>
</table>
<% end %>
<% end %>
<% end %>
できあがりのイメージ
おおお!できましたね!!!

I'm a software engineer who like travel to island in Japanese. Recently I am enjoying agile manager, coach, product owner for my work. The person grows like that.








