Commit 043cb37b authored by Jean-Philippe Lang's avatar Jean-Philippe Lang

Add predefined date ranges to the time report in the same way as the details…

Add predefined date ranges to the time report in the same way as the details view (closes #972). It nows defaults to 'All time'.
This patch also fixes time report periods (columns) computation.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1318 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent e4da9d6f
...@@ -53,16 +53,11 @@ class TimelogController < ApplicationController ...@@ -53,16 +53,11 @@ class TimelogController < ApplicationController
@criterias.uniq! @criterias.uniq!
@criterias = @criterias[0,3] @criterias = @criterias[0,3]
@columns = (params[:period] && %w(year month week).include?(params[:period])) ? params[:period] : 'month' @columns = (params[:columns] && %w(year month week).include?(params[:columns])) ? params[:columns] : 'month'
if params[:date_from] retrieve_date_range
begin; @date_from = params[:date_from].to_date; rescue; end @from ||= TimeEntry.minimum(:spent_on, :include => :project, :conditions => @project.project_condition(Setting.display_subprojects_issues?)) || Date.today
end @to ||= TimeEntry.maximum(:spent_on, :include => :project, :conditions => @project.project_condition(Setting.display_subprojects_issues?)) || Date.today
if params[:date_to]
begin; @date_to = params[:date_to].to_date; rescue; end
end
@date_from ||= Date.civil(Date.today.year, 1, 1)
@date_to ||= (Date.civil(Date.today.year, Date.today.month, 1) >> 1) - 1
unless @criterias.empty? unless @criterias.empty?
sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ') sql_select = @criterias.collect{|criteria| @available_criterias[criteria][:sql] + " AS " + criteria}.join(', ')
...@@ -74,7 +69,7 @@ class TimelogController < ApplicationController ...@@ -74,7 +69,7 @@ class TimelogController < ApplicationController
sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id" sql << " LEFT JOIN #{Project.table_name} ON #{TimeEntry.table_name}.project_id = #{Project.table_name}.id"
sql << " WHERE (%s)" % @project.project_condition(Setting.display_subprojects_issues?) sql << " WHERE (%s)" % @project.project_condition(Setting.display_subprojects_issues?)
sql << " AND (%s)" % Project.allowed_to_condition(User.current, :view_time_entries) sql << " AND (%s)" % Project.allowed_to_condition(User.current, :view_time_entries)
sql << " AND spent_on BETWEEN '%s' AND '%s'" % [ActiveRecord::Base.connection.quoted_date(@date_from.to_time), ActiveRecord::Base.connection.quoted_date(@date_to.to_time)] sql << " AND spent_on BETWEEN '%s' AND '%s'" % [ActiveRecord::Base.connection.quoted_date(@from.to_time), ActiveRecord::Base.connection.quoted_date(@to.to_time)]
sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek" sql << " GROUP BY #{sql_group_by}, tyear, tmonth, tweek"
@hours = ActiveRecord::Base.connection.select_all(sql) @hours = ActiveRecord::Base.connection.select_all(sql)
...@@ -91,22 +86,23 @@ class TimelogController < ApplicationController ...@@ -91,22 +86,23 @@ class TimelogController < ApplicationController
end end
@total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f} @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
end
@periods = []
@periods = [] # Date#at_beginning_of_ not supported in Rails 1.2.x
date_from = @date_from date_from = @from.to_time
# 100 columns max # 100 columns max
while date_from < @date_to && @periods.length < 100 while date_from <= @to.to_time && @periods.length < 100
case @columns case @columns
when 'year' when 'year'
@periods << "#{date_from.year}" @periods << "#{date_from.year}"
date_from = date_from >> 12 date_from = (date_from + 1.year).at_beginning_of_year
when 'month' when 'month'
@periods << "#{date_from.year}-#{date_from.month}" @periods << "#{date_from.year}-#{date_from.month}"
date_from = date_from >> 1 date_from = (date_from + 1.month).at_beginning_of_month
when 'week' when 'week'
@periods << "#{date_from.year}-#{date_from.cweek}" @periods << "#{date_from.year}-#{date_from.to_date.cweek}"
date_from = date_from + 7 date_from = (date_from + 7.day).at_beginning_of_week
end
end end
end end
...@@ -116,52 +112,13 @@ class TimelogController < ApplicationController ...@@ -116,52 +112,13 @@ class TimelogController < ApplicationController
def details def details
sort_init 'spent_on', 'desc' sort_init 'spent_on', 'desc'
sort_update sort_update
@free_period = false
@from, @to = nil, nil
if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?)
case params[:period].to_s
when 'today'
@from = @to = Date.today
when 'yesterday'
@from = @to = Date.today - 1
when 'current_week'
@from = Date.today - (Date.today.cwday - 1)%7
@to = @from + 6
when 'last_week'
@from = Date.today - 7 - (Date.today.cwday - 1)%7
@to = @from + 6
when '7_days'
@from = Date.today - 7
@to = Date.today
when 'current_month'
@from = Date.civil(Date.today.year, Date.today.month, 1)
@to = (@from >> 1) - 1
when 'last_month'
@from = Date.civil(Date.today.year, Date.today.month, 1) << 1
@to = (@from >> 1) - 1
when '30_days'
@from = Date.today - 30
@to = Date.today
when 'current_year'
@from = Date.civil(Date.today.year, 1, 1)
@to = Date.civil(Date.today.year, 12, 31)
end
elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?))
begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end
begin; @to = params[:to].to_s.to_date unless params[:to].blank?; rescue; end
@free_period = true
else
# default
end
@from, @to = @to, @from if @from && @to && @from > @to
cond = ARCondition.new cond = ARCondition.new
cond << (@issue.nil? ? @project.project_condition(Setting.display_subprojects_issues?) : cond << (@issue.nil? ? @project.project_condition(Setting.display_subprojects_issues?) :
["#{TimeEntry.table_name}.issue_id = ?", @issue.id]) ["#{TimeEntry.table_name}.issue_id = ?", @issue.id])
retrieve_date_range
if @from if @from
if @to if @to
cond << ['spent_on BETWEEN ? AND ?', @from, @to] cond << ['spent_on BETWEEN ? AND ?', @from, @to]
...@@ -238,4 +195,48 @@ private ...@@ -238,4 +195,48 @@ private
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render_404 render_404
end end
# Retreive the date range based on predefined ranges or specific from/to param dates
def retrieve_date_range
@free_period = false
@from, @to = nil, nil
if params[:period_type] == '1' || (params[:period_type].nil? && !params[:period].nil?)
case params[:period].to_s
when 'today'
@from = @to = Date.today
when 'yesterday'
@from = @to = Date.today - 1
when 'current_week'
@from = Date.today - (Date.today.cwday - 1)%7
@to = @from + 6
when 'last_week'
@from = Date.today - 7 - (Date.today.cwday - 1)%7
@to = @from + 6
when '7_days'
@from = Date.today - 7
@to = Date.today
when 'current_month'
@from = Date.civil(Date.today.year, Date.today.month, 1)
@to = (@from >> 1) - 1
when 'last_month'
@from = Date.civil(Date.today.year, Date.today.month, 1) << 1
@to = (@from >> 1) - 1
when '30_days'
@from = Date.today - 30
@to = Date.today
when 'current_year'
@from = Date.civil(Date.today.year, 1, 1)
@to = Date.civil(Date.today.year, 12, 31)
end
elsif params[:period_type] == '2' || (params[:period_type].nil? && (!params[:from].nil? || !params[:to].nil?))
begin; @from = params[:from].to_s.to_date unless params[:from].blank?; rescue; end
begin; @to = params[:to].to_s.to_date unless params[:to].blank?; rescue; end
@free_period = true
else
# default
end
@from, @to = @to, @from if @from && @to && @from > @to
end
end end
<fieldset><legend><%= l(:label_date_range) %></legend>
<p>
<%= radio_button_tag 'period_type', '1', !@free_period %>
<%= select_tag 'period', options_for_period_select(params[:period]),
:onchange => 'this.form.onsubmit();',
:onfocus => '$("period_type_1").checked = true;' %>
</p>
<p>
<%= radio_button_tag 'period_type', '2', @free_period %>
<%= l(:label_date_from) %>
<%= text_field_tag 'from', @from, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('from') %>
<%= l(:label_date_to) %>
<%= text_field_tag 'to', @to, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('to') %>
<%= submit_tag l(:button_apply), :name => nil, :onclick => '$("period_type_2").checked = true;' %>
</p>
</fieldset>
...@@ -12,23 +12,7 @@ ...@@ -12,23 +12,7 @@
<% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %> <% form_remote_tag( :url => {}, :method => :get, :update => 'content' ) do %>
<%= hidden_field_tag 'project_id', params[:project_id] %> <%= hidden_field_tag 'project_id', params[:project_id] %>
<%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %> <%= hidden_field_tag 'issue_id', params[:issue_id] if @issue %>
<%= render :partial => 'date_range' %>
<fieldset><legend><%= l(:label_date_range) %></legend>
<p>
<%= radio_button_tag 'period_type', '1', !@free_period %>
<%= select_tag 'period', options_for_period_select(params[:period]),
:onchange => 'this.form.onsubmit();',
:onfocus => '$("period_type_1").checked = true;' %>
</p>
<p>
<%= radio_button_tag 'period_type', '2', @free_period %>
<%= l(:label_date_from) %>
<%= text_field_tag 'from', @from, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('from') %>
<%= l(:label_date_to) %>
<%= text_field_tag 'to', @to, :size => 10, :onfocus => '$("period_type_2").checked = true;' %> <%= calendar_for('to') %>
<%= submit_tag l(:button_apply), :name => nil, :onclick => '$("period_type_2").checked = true;' %>
</p>
</fieldset>
<% end %> <% end %>
<div class="total-hours"> <div class="total-hours">
......
...@@ -5,32 +5,27 @@ ...@@ -5,32 +5,27 @@
<h2><%= l(:label_spent_time) %></h2> <h2><%= l(:label_spent_time) %></h2>
<% form_remote_tag(:url => {:project_id => @project}, :update => 'content') do %> <% form_remote_tag(:url => {}, :update => 'content') do %>
<% @criterias.each do |criteria| %> <% @criterias.each do |criteria| %>
<%= hidden_field_tag 'criterias[]', criteria %> <%= hidden_field_tag 'criterias[]', criteria %>
<% end %> <% end %>
<fieldset><legend><%= l(:label_date_range) %></legend> <%= hidden_field_tag 'project_id', params[:project_id] %>
<p> <%= render :partial => 'date_range' %>
<%= l(:label_date_from) %>
<%= text_field_tag 'date_from', @date_from, :size => 10 %><%= calendar_for('date_from') %>
<%= l(:label_date_to) %>
<%= text_field_tag 'date_to', @date_to, :size => 10 %><%= calendar_for('date_to') %>
<%= l(:label_details) %>
<%= select_tag 'period', options_for_select([[l(:label_year), 'year'],
[l(:label_month), 'month'],
[l(:label_week), 'week']], @columns) %>
&nbsp;
<%= submit_tag l(:button_apply) %>
</p> </p>
</fieldset> </fieldset>
<p><%= l(:label_details) %>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
[l(:label_month), 'month'],
[l(:label_week), 'week']], @columns),
:onchange => "this.form.onsubmit();" %>
<p><%= l(:button_add) %>: <%= select_tag('criterias[]', options_for_select([[]] + (@available_criterias.keys - @criterias).collect{|k| [l(@available_criterias[k][:label]), k]}), <%= l(:button_add) %>: <%= select_tag('criterias[]', options_for_select([[]] + (@available_criterias.keys - @criterias).collect{|k| [l(@available_criterias[k][:label]), k]}),
:onchange => "this.form.onsubmit();", :onchange => "this.form.onsubmit();",
:style => 'width: 200px', :style => 'width: 200px',
:disabled => (@criterias.length >= 3)) %> :disabled => (@criterias.length >= 3)) %>
<%= link_to_remote l(:button_clear), {:url => {:project_id => @project, :date_from => @date_from, :date_to => @date_to, :period => @columns}, :update => 'content'}, <%= link_to_remote l(:button_clear), {:url => {:project_id => @project, :date_from => @date_from, :date_to => @date_to, :period => @columns}, :update => 'content'},
:class => 'icon icon-reload' %></p> :class => 'icon icon-reload' %></p>
<% end %>
<% unless @criterias.empty? %> <% unless @criterias.empty? %>
<div class="total-hours"> <div class="total-hours">
<p><%= l(:label_total) %>: <%= html_hours(lwr(:label_f_hour, @total_hours)) %></p> <p><%= l(:label_total) %>: <%= html_hours(lwr(:label_f_hour, @total_hours)) %></p>
...@@ -62,4 +57,3 @@ ...@@ -62,4 +57,3 @@
</table> </table>
<% end %> <% end %>
<% end %> <% end %>
<% end %>
...@@ -78,17 +78,25 @@ class TimelogControllerTest < Test::Unit::TestCase ...@@ -78,17 +78,25 @@ class TimelogControllerTest < Test::Unit::TestCase
assert_response :success assert_response :success
assert_template 'report' assert_template 'report'
end end
def test_report_all_time
get :report, :project_id => 1, :criterias => ['project']
assert_response :success
assert_template 'report'
assert_not_nil assigns(:total_hours)
assert_equal "162.90", "%.2f" % assigns(:total_hours)
end
def test_report_one_criteria def test_report_one_criteria
get :report, :project_id => 1, :period => 'week', :date_from => "2007-04-01", :date_to => "2007-04-30", :criterias => ['project'] get :report, :project_id => 1, :columns => 'week', :from => "2007-04-01", :to => "2007-04-30", :criterias => ['project']
assert_response :success assert_response :success
assert_template 'report' assert_template 'report'
assert_not_nil assigns(:total_hours) assert_not_nil assigns(:total_hours)
assert_equal "8.65", "%.2f" % assigns(:total_hours) assert_equal "8.65", "%.2f" % assigns(:total_hours)
end end
def test_report_two_criterias def test_report_two_criterias
get :report, :project_id => 1, :period => 'month', :date_from => "2007-01-01", :date_to => "2007-12-31", :criterias => ["member", "activity"] get :report, :project_id => 1, :columns => 'month', :from => "2007-01-01", :to => "2007-12-31", :criterias => ["member", "activity"]
assert_response :success assert_response :success
assert_template 'report' assert_template 'report'
assert_not_nil assigns(:total_hours) assert_not_nil assigns(:total_hours)
...@@ -96,7 +104,7 @@ class TimelogControllerTest < Test::Unit::TestCase ...@@ -96,7 +104,7 @@ class TimelogControllerTest < Test::Unit::TestCase
end end
def test_report_one_criteria_no_result def test_report_one_criteria_no_result
get :report, :project_id => 1, :period => 'week', :date_from => "1998-04-01", :date_to => "1998-04-30", :criterias => ['project'] get :report, :project_id => 1, :columns => 'week', :from => "1998-04-01", :to => "1998-04-30", :criterias => ['project']
assert_response :success assert_response :success
assert_template 'report' assert_template 'report'
assert_not_nil assigns(:total_hours) assert_not_nil assigns(:total_hours)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment