##// END OF EJS Templates
Adds TimeEntryQuery for listing time entries....
Jean-Philippe Lang -
r10740:f8895a7cdd9c
parent child
Show More
@@ -0,0 +1,65
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 class TimeEntryQuery < Query
19
20 self.queried_class = TimeEntry
21
22 self.available_columns = [
23 QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
24 QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"]),
25 QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
26 QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true),
27 QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"),
28 QueryColumn.new(:comments),
29 QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours"),
30 ]
31
32 def initialize(attributes=nil, *args)
33 super attributes
34 self.filters ||= {}
35 add_filter('spent_on', '*') unless filters.present?
36 end
37
38 def available_filters
39 return @available_filters if @available_filters
40 @available_filters = {
41 "spent_on" => { :type => :date_past, :order => 0 }
42 }
43 @available_filters.each do |field, options|
44 options[:name] ||= l(options[:label] || "field_#{field}".gsub(/_id$/, ''))
45 end
46 @available_filters
47 end
48
49 def default_columns_names
50 @default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
51 end
52
53 # Accepts :from/:to params as shortcut filters
54 def build_from_params(params)
55 super
56 if params[:from].present? && params[:to].present?
57 add_filter('spent_on', '><', [params[:from], params[:to]])
58 elsif params[:from].present?
59 add_filter('spent_on', '>=', [params[:from]])
60 elsif params[:to].present?
61 add_filter('spent_on', '<=', [params[:to]])
62 end
63 self
64 end
65 end
@@ -36,24 +36,14 class TimelogController < ApplicationController
36 include TimelogHelper
36 include TimelogHelper
37 helper :custom_fields
37 helper :custom_fields
38 include CustomFieldsHelper
38 include CustomFieldsHelper
39 helper :queries
39
40
40 def index
41 def index
41 sort_init 'spent_on', 'desc'
42 @query = TimeEntryQuery.build_from_params(params, :name => '_')
42 sort_update 'spent_on' => ['spent_on', "#{TimeEntry.table_name}.created_on"],
43 scope = time_entry_scope
43 'user' => 'user_id',
44 'activity' => 'activity_id',
45 'project' => "#{Project.table_name}.name",
46 'issue' => 'issue_id',
47 'hours' => 'hours'
48
44
49 retrieve_date_range
45 sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
50
46 sort_update(@query.sortable_columns)
51 scope = TimeEntry.visible.spent_between(@from, @to)
52 if @issue
53 scope = scope.on_issue(@issue)
54 elsif @project
55 scope = scope.on_project(@project, Setting.display_subprojects_issues?)
56 end
57
47
58 respond_to do |format|
48 respond_to do |format|
59 format.html {
49 format.html {
@@ -100,8 +90,10 class TimelogController < ApplicationController
100 end
90 end
101
91
102 def report
92 def report
103 retrieve_date_range
93 @query = TimeEntryQuery.build_from_params(params, :name => '_')
104 @report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], @from, @to)
94 scope = time_entry_scope
95
96 @report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
105
97
106 respond_to do |format|
98 respond_to do |format|
107 format.html { render :layout => !request.xhr? }
99 format.html { render :layout => !request.xhr? }
@@ -291,6 +283,17 private
291 end
283 end
292 end
284 end
293
285
286 # Returns the TimeEntry scope for index and report actions
287 def time_entry_scope
288 scope = TimeEntry.visible.where(@query.statement)
289 if @issue
290 scope = scope.on_issue(@issue)
291 elsif @project
292 scope = scope.on_project(@project, Setting.display_subprojects_issues?)
293 end
294 scope
295 end
296
294 # Retrieves the date range based on predefined ranges or specific from/to param dates
297 # Retrieves the date range based on predefined ranges or specific from/to param dates
295 def retrieve_date_range
298 def retrieve_date_range
296 @free_period = false
299 @free_period = false
@@ -117,7 +117,13 class Query < ActiveRecord::Base
117 "><t+"=> :label_in_the_next_days,
117 "><t+"=> :label_in_the_next_days,
118 "t+" => :label_in,
118 "t+" => :label_in,
119 "t" => :label_today,
119 "t" => :label_today,
120 "ld" => :label_yesterday,
120 "w" => :label_this_week,
121 "w" => :label_this_week,
122 "lw" => :label_last_week,
123 "l2w" => [:label_last_n_weeks, :count => 2],
124 "m" => :label_this_month,
125 "lm" => :label_last_month,
126 "y" => :label_this_year,
121 ">t-" => :label_less_than_ago,
127 ">t-" => :label_less_than_ago,
122 "<t-" => :label_more_than_ago,
128 "<t-" => :label_more_than_ago,
123 "><t-"=> :label_in_the_past_days,
129 "><t-"=> :label_in_the_past_days,
@@ -135,8 +141,8 class Query < ActiveRecord::Base
135 :list_status => [ "o", "=", "!", "c", "*" ],
141 :list_status => [ "o", "=", "!", "c", "*" ],
136 :list_optional => [ "=", "!", "!*", "*" ],
142 :list_optional => [ "=", "!", "!*", "*" ],
137 :list_subprojects => [ "*", "!*", "=" ],
143 :list_subprojects => [ "*", "!*", "=" ],
138 :date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "t", "w", ">t-", "<t-", "><t-", "t-", "!*", "*" ],
144 :date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", ">t-", "<t-", "><t-", "t-", "!*", "*" ],
139 :date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "w", "!*", "*" ],
145 :date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "!*", "*" ],
140 :string => [ "=", "~", "!", "!~", "!*", "*" ],
146 :string => [ "=", "~", "!", "!~", "!*", "*" ],
141 :text => [ "~", "!~", "!*", "*" ],
147 :text => [ "~", "!~", "!*", "*" ],
142 :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
148 :integer => [ "=", ">=", "<=", "><", "!*", "*" ],
@@ -173,6 +179,11 class Query < ActiveRecord::Base
173 self
179 self
174 end
180 end
175
181
182 # Builds a new query from the given params and attributes
183 def self.build_from_params(params, attributes={})
184 new(attributes).build_from_params(params)
185 end
186
176 def validate_query_filters
187 def validate_query_filters
177 filters.each_key do |field|
188 filters.each_key do |field|
178 if values_for(field)
189 if values_for(field)
@@ -195,7 +206,7 class Query < ActiveRecord::Base
195 # filter requires one or more values
206 # filter requires one or more values
196 (values_for(field) and !values_for(field).first.blank?) or
207 (values_for(field) and !values_for(field).first.blank?) or
197 # filter doesn't require any value
208 # filter doesn't require any value
198 ["o", "c", "!*", "*", "t", "w"].include? operator_for(field)
209 ["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y"].include? operator_for(field)
199 end if filters
210 end if filters
200 end
211 end
201
212
@@ -218,7 +229,7 class Query < ActiveRecord::Base
218
229
219 # Returns a hash of localized labels for all filter operators
230 # Returns a hash of localized labels for all filter operators
220 def self.operators_labels
231 def self.operators_labels
221 operators.inject({}) {|h, operator| h[operator.first] = l(operator.last); h}
232 operators.inject({}) {|h, operator| h[operator.first] = l(*operator.last); h}
222 end
233 end
223
234
224 # Returns a representation of the available filters for JSON serialization
235 # Returns a representation of the available filters for JSON serialization
@@ -245,7 +256,7 class Query < ActiveRecord::Base
245 @all_projects_values = values
256 @all_projects_values = values
246 end
257 end
247
258
248 def add_filter(field, operator, values)
259 def add_filter(field, operator, values=nil)
249 # values must be an array
260 # values must be an array
250 return unless values.nil? || values.is_a?(Array)
261 return unless values.nil? || values.is_a?(Array)
251 # check if field is defined as an available filter
262 # check if field is defined as an available filter
@@ -612,12 +623,39 class Query < ActiveRecord::Base
612 when "t"
623 when "t"
613 # = today
624 # = today
614 sql = relative_date_clause(db_table, db_field, 0, 0)
625 sql = relative_date_clause(db_table, db_field, 0, 0)
626 when "ld"
627 # = yesterday
628 sql = relative_date_clause(db_table, db_field, -1, -1)
615 when "w"
629 when "w"
616 # = this week
630 # = this week
617 first_day_of_week = l(:general_first_day_of_week).to_i
631 first_day_of_week = l(:general_first_day_of_week).to_i
618 day_of_week = Date.today.cwday
632 day_of_week = Date.today.cwday
619 days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
633 days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
620 sql = relative_date_clause(db_table, db_field, - days_ago, - days_ago + 6)
634 sql = relative_date_clause(db_table, db_field, - days_ago, - days_ago + 6)
635 when "lw"
636 # = last week
637 first_day_of_week = l(:general_first_day_of_week).to_i
638 day_of_week = Date.today.cwday
639 days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
640 sql = relative_date_clause(db_table, db_field, - days_ago - 7, - days_ago - 1)
641 when "l2w"
642 # = last 2 weeks
643 first_day_of_week = l(:general_first_day_of_week).to_i
644 day_of_week = Date.today.cwday
645 days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
646 sql = relative_date_clause(db_table, db_field, - days_ago - 14, - days_ago - 1)
647 when "m"
648 # = this month
649 date = Date.today
650 sql = date_clause(db_table, db_field, date.beginning_of_month, date.end_of_month)
651 when "lm"
652 # = last month
653 date = Date.today.prev_month
654 sql = date_clause(db_table, db_field, date.beginning_of_month, date.end_of_month)
655 when "y"
656 # = this year
657 date = Date.today
658 sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year)
621 when "~"
659 when "~"
622 sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
660 sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
623 when "!~"
661 when "!~"
@@ -1,42 +1,23
1 <fieldset id="date-range" class="collapsible">
1 <div id="query_form_content" class="hide-when-print">
2 <legend onclick="toggleFieldset(this);"><%= l(:label_date_range) %></legend>
2 <fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
3 <div>
3 <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
4 <p>
4 <div style="<%= @query.new_record? ? "" : "display: none;" %>">
5 <%= label_tag "period_type_list", l(:description_date_range_list), :class => "hidden-for-sighted" %>
5 <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
6 <%= radio_button_tag 'period_type', '1', !@free_period, :onclick => '$("#from,#to").attr("disabled", true);$("#period").removeAttr("disabled");', :id => "period_type_list"%>
6 </div>
7 <%= select_tag 'period', options_for_period_select(params[:period]),
8 :onchange => 'this.form.submit();',
9 :onfocus => '$("#period_type_1").attr("checked", true);',
10 :disabled => @free_period %>
11 </p>
12 <p>
13 <%= label_tag "period_type_interval", l(:description_date_range_interval), :class => "hidden-for-sighted" %>
14 <%= radio_button_tag 'period_type', '2', @free_period, :onclick => '$("#from,#to").removeAttr("disabled");$("#period").attr("disabled", true);', :id => "period_type_interval" %>
15 <%= l(:label_date_from_to,
16 :start => ((label_tag "from", l(:description_date_from), :class => "hidden-for-sighted") +
17 text_field_tag('from', @from, :size => 10, :disabled => !@free_period) + calendar_for('from')),
18 :end => ((label_tag "to", l(:description_date_to), :class => "hidden-for-sighted") +
19 text_field_tag('to', @to, :size => 10, :disabled => !@free_period) + calendar_for('to'))).html_safe %>
20 </p>
21 </div>
22 </fieldset>
7 </fieldset>
23 <p class="buttons">
8 </div>
9
10 <p class="buttons hide-when-print">
24 <%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
11 <%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
25 <%= link_to l(:button_clear), {:controller => controller_name, :action => action_name, :project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
12 <%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
26 </p>
13 </p>
27
14
28 <div class="tabs">
15 <div class="tabs">
29 <% url_params = @free_period ? { :from => @from, :to => @to } : { :period => params[:period] } %>
16 <% query_params = params.slice(:f, :op, :v, :sort) %>
30 <ul>
17 <ul>
31 <li><%= link_to(l(:label_details), url_params.merge({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue }),
18 <li><%= link_to(l(:label_details), query_params.merge({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue }),
32 :class => (action_name == 'index' ? 'selected' : nil)) %></li>
19 :class => (action_name == 'index' ? 'selected' : nil)) %></li>
33 <li><%= link_to(l(:label_report), url_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
20 <li><%= link_to(l(:label_report), query_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
34 :class => (action_name == 'report' ? 'selected' : nil)) %></li>
21 :class => (action_name == 'report' ? 'selected' : nil)) %></li>
35 </ul>
22 </ul>
36 </div>
23 </div>
37
38 <%= javascript_tag do %>
39 $('#from, #to').change(function(){
40 $('#period_type_interval').attr('checked', true); $('#from,#to').removeAttr('disabled'); $('#period').attr('disabled', true);
41 });
42 <% end %>
@@ -18,9 +18,9
18 module Redmine
18 module Redmine
19 module Helpers
19 module Helpers
20 class TimeReport
20 class TimeReport
21 attr_reader :criteria, :columns, :from, :to, :hours, :total_hours, :periods
21 attr_reader :criteria, :columns, :hours, :total_hours, :periods
22
22
23 def initialize(project, issue, criteria, columns, from, to)
23 def initialize(project, issue, criteria, columns, time_entry_scope)
24 @project = project
24 @project = project
25 @issue = issue
25 @issue = issue
26
26
@@ -30,8 +30,7 module Redmine
30 @criteria = @criteria[0,3]
30 @criteria = @criteria[0,3]
31
31
32 @columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
32 @columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
33 @from = from
33 @scope = time_entry_scope
34 @to = to
35
34
36 run
35 run
37 end
36 end
@@ -44,15 +43,9 module Redmine
44
43
45 def run
44 def run
46 unless @criteria.empty?
45 unless @criteria.empty?
47 scope = TimeEntry.visible.spent_between(@from, @to)
48 if @issue
49 scope = scope.on_issue(@issue)
50 elsif @project
51 scope = scope.on_project(@project, Setting.display_subprojects_issues?)
52 end
53 time_columns = %w(tyear tmonth tweek spent_on)
46 time_columns = %w(tyear tmonth tweek spent_on)
54 @hours = []
47 @hours = []
55 scope.sum(:hours, :include => :issue, :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns).each do |hash, hours|
48 @scope.sum(:hours, :include => :issue, :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns).each do |hash, hours|
56 h = {'hours' => hours}
49 h = {'hours' => hours}
57 (@criteria + time_columns).each_with_index do |name, i|
50 (@criteria + time_columns).each_with_index do |name, i|
58 h[name] = hash[i]
51 h[name] = hash[i]
@@ -73,15 +66,11 module Redmine
73 end
66 end
74 end
67 end
75
68
76 if @from.nil?
69 min = @hours.collect {|row| row['spent_on']}.min
77 min = @hours.collect {|row| row['spent_on']}.min
70 @from = min ? min.to_date : Date.today
78 @from = min ? min.to_date : Date.today
79 end
80
71
81 if @to.nil?
72 max = @hours.collect {|row| row['spent_on']}.max
82 max = @hours.collect {|row| row['spent_on']}.max
73 @to = max ? max.to_date : Date.today
83 @to = max ? max.to_date : Date.today
84 end
85
74
86 @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
75 @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
87
76
@@ -242,7 +242,13 function toggleOperator(field) {
242 case "!*":
242 case "!*":
243 case "*":
243 case "*":
244 case "t":
244 case "t":
245 case "ld":
245 case "w":
246 case "w":
247 case "lw":
248 case "l2w":
249 case "m":
250 case "lm":
251 case "y":
246 case "o":
252 case "o":
247 case "c":
253 case "c":
248 enableValues(field, []);
254 enableValues(field, []);
@@ -166,10 +166,9 class TimeEntryReportsControllerTest < ActionController::TestCase
166 assert_equal 'text/csv; header=present', @response.content_type
166 assert_equal 'text/csv; header=present', @response.content_type
167 lines = @response.body.chomp.split("\n")
167 lines = @response.body.chomp.split("\n")
168 # Headers
168 # Headers
169 assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total',
169 assert_equal 'Project,Member,Activity,2007-3,2007-4,Total', lines.first
170 lines.first
171 # Total row
170 # Total row
172 assert_equal 'Total,"","","","",154.25,8.65,"","",162.90', lines.last
171 assert_equal 'Total,"","",154.25,8.65,162.90', lines.last
173 end
172 end
174
173
175 def test_report_csv_export
174 def test_report_csv_export
@@ -180,10 +179,9 class TimeEntryReportsControllerTest < ActionController::TestCase
180 assert_equal 'text/csv; header=present', @response.content_type
179 assert_equal 'text/csv; header=present', @response.content_type
181 lines = @response.body.chomp.split("\n")
180 lines = @response.body.chomp.split("\n")
182 # Headers
181 # Headers
183 assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total',
182 assert_equal 'Project,Member,Activity,2007-3,2007-4,Total', lines.first
184 lines.first
185 # Total row
183 # Total row
186 assert_equal 'Total,"","","","",154.25,8.65,"","",162.90', lines.last
184 assert_equal 'Total,"","",154.25,8.65,162.90', lines.last
187 end
185 end
188
186
189 def test_csv_big_5
187 def test_csv_big_5
@@ -430,131 +430,50 class TimelogControllerTest < ActionController::TestCase
430 assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
430 assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
431 assert_not_nil assigns(:total_hours)
431 assert_not_nil assigns(:total_hours)
432 assert_equal "162.90", "%.2f" % assigns(:total_hours)
432 assert_equal "162.90", "%.2f" % assigns(:total_hours)
433 # display all time by default
434 assert_nil assigns(:from)
435 assert_nil assigns(:to)
436 assert_tag :form,
433 assert_tag :form,
437 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
434 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
438 end
435 end
439
436
440 def test_index_at_project_level_with_date_range
437 def test_index_at_project_level_with_date_range
441 get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
438 get :index, :project_id => 'ecookbook',
439 :f => ['spent_on'],
440 :op => {'spent_on' => '><'},
441 :v => {'spent_on' => ['2007-03-20', '2007-04-30']}
442 assert_response :success
442 assert_response :success
443 assert_template 'index'
443 assert_template 'index'
444 assert_not_nil assigns(:entries)
444 assert_not_nil assigns(:entries)
445 assert_equal 3, assigns(:entries).size
445 assert_equal 3, assigns(:entries).size
446 assert_not_nil assigns(:total_hours)
446 assert_not_nil assigns(:total_hours)
447 assert_equal "12.90", "%.2f" % assigns(:total_hours)
447 assert_equal "12.90", "%.2f" % assigns(:total_hours)
448 assert_equal '2007-03-20'.to_date, assigns(:from)
449 assert_equal '2007-04-30'.to_date, assigns(:to)
450 assert_tag :form,
448 assert_tag :form,
451 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
449 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
452 end
450 end
453
451
454 def test_index_at_project_level_with_period
452 def test_index_at_project_level_with_date_range_using_from_and_to_params
455 get :index, :project_id => 'ecookbook', :period => '7_days'
453 get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
456 assert_response :success
454 assert_response :success
457 assert_template 'index'
455 assert_template 'index'
458 assert_not_nil assigns(:entries)
456 assert_not_nil assigns(:entries)
457 assert_equal 3, assigns(:entries).size
459 assert_not_nil assigns(:total_hours)
458 assert_not_nil assigns(:total_hours)
460 assert_equal Date.today - 7, assigns(:from)
459 assert_equal "12.90", "%.2f" % assigns(:total_hours)
461 assert_equal Date.today, assigns(:to)
462 assert_tag :form,
460 assert_tag :form,
463 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
461 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
464 end
462 end
465
463
466 def test_index_one_day
464 def test_index_at_project_level_with_period
467 get :index, :project_id => 'ecookbook', :from => "2007-03-23", :to => "2007-03-23"
465 get :index, :project_id => 'ecookbook',
466 :f => ['spent_on'],
467 :op => {'spent_on' => '>t-'},
468 :v => {'spent_on' => ['7']}
468 assert_response :success
469 assert_response :success
469 assert_template 'index'
470 assert_template 'index'
471 assert_not_nil assigns(:entries)
470 assert_not_nil assigns(:total_hours)
472 assert_not_nil assigns(:total_hours)
471 assert_equal "4.25", "%.2f" % assigns(:total_hours)
472 assert_tag :form,
473 assert_tag :form,
473 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
474 :attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
474 end
475 end
475
476
476 def test_index_from_a_date
477 get :index, :project_id => 'ecookbook', :from => "2007-03-23", :to => ""
478 assert_equal '2007-03-23'.to_date, assigns(:from)
479 assert_nil assigns(:to)
480 end
481
482 def test_index_to_a_date
483 get :index, :project_id => 'ecookbook', :from => "", :to => "2007-03-23"
484 assert_nil assigns(:from)
485 assert_equal '2007-03-23'.to_date, assigns(:to)
486 end
487
488 def test_index_today
489 Date.stubs(:today).returns('2011-12-15'.to_date)
490 get :index, :period => 'today'
491 assert_equal '2011-12-15'.to_date, assigns(:from)
492 assert_equal '2011-12-15'.to_date, assigns(:to)
493 end
494
495 def test_index_yesterday
496 Date.stubs(:today).returns('2011-12-15'.to_date)
497 get :index, :period => 'yesterday'
498 assert_equal '2011-12-14'.to_date, assigns(:from)
499 assert_equal '2011-12-14'.to_date, assigns(:to)
500 end
501
502 def test_index_current_week
503 Date.stubs(:today).returns('2011-12-15'.to_date)
504 get :index, :period => 'current_week'
505 assert_equal '2011-12-12'.to_date, assigns(:from)
506 assert_equal '2011-12-18'.to_date, assigns(:to)
507 end
508
509 def test_index_last_week
510 Date.stubs(:today).returns('2011-12-15'.to_date)
511 get :index, :period => 'last_week'
512 assert_equal '2011-12-05'.to_date, assigns(:from)
513 assert_equal '2011-12-11'.to_date, assigns(:to)
514 end
515
516 def test_index_last_2_week
517 Date.stubs(:today).returns('2011-12-15'.to_date)
518 get :index, :period => 'last_2_weeks'
519 assert_equal '2011-11-28'.to_date, assigns(:from)
520 assert_equal '2011-12-11'.to_date, assigns(:to)
521 end
522
523 def test_index_7_days
524 Date.stubs(:today).returns('2011-12-15'.to_date)
525 get :index, :period => '7_days'
526 assert_equal '2011-12-08'.to_date, assigns(:from)
527 assert_equal '2011-12-15'.to_date, assigns(:to)
528 end
529
530 def test_index_current_month
531 Date.stubs(:today).returns('2011-12-15'.to_date)
532 get :index, :period => 'current_month'
533 assert_equal '2011-12-01'.to_date, assigns(:from)
534 assert_equal '2011-12-31'.to_date, assigns(:to)
535 end
536
537 def test_index_last_month
538 Date.stubs(:today).returns('2011-12-15'.to_date)
539 get :index, :period => 'last_month'
540 assert_equal '2011-11-01'.to_date, assigns(:from)
541 assert_equal '2011-11-30'.to_date, assigns(:to)
542 end
543
544 def test_index_30_days
545 Date.stubs(:today).returns('2011-12-15'.to_date)
546 get :index, :period => '30_days'
547 assert_equal '2011-11-15'.to_date, assigns(:from)
548 assert_equal '2011-12-15'.to_date, assigns(:to)
549 end
550
551 def test_index_current_year
552 Date.stubs(:today).returns('2011-12-15'.to_date)
553 get :index, :period => 'current_year'
554 assert_equal '2011-01-01'.to_date, assigns(:from)
555 assert_equal '2011-12-31'.to_date, assigns(:to)
556 end
557
558 def test_index_at_issue_level
477 def test_index_at_issue_level
559 get :index, :issue_id => 1
478 get :index, :issue_id => 1
560 assert_response :success
479 assert_response :success
@@ -577,11 +496,18 class TimelogControllerTest < ActionController::TestCase
577 t2 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:05:00', :activity_id => 10)
496 t2 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-16', :created_on => '2012-06-16 20:05:00', :activity_id => 10)
578 t3 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-15', :created_on => '2012-06-16 20:10:00', :activity_id => 10)
497 t3 = TimeEntry.create!(:user => User.find(1), :project => Project.find(1), :hours => 1, :spent_on => '2012-06-15', :created_on => '2012-06-16 20:10:00', :activity_id => 10)
579
498
580 get :index, :project_id => 1, :from => '2012-06-15', :to => '2012-06-16'
499 get :index, :project_id => 1,
500 :f => ['spent_on'],
501 :op => {'spent_on' => '><'},
502 :v => {'spent_on' => ['2012-06-15', '2012-06-16']}
581 assert_response :success
503 assert_response :success
582 assert_equal [t2, t1, t3], assigns(:entries)
504 assert_equal [t2, t1, t3], assigns(:entries)
583
505
584 get :index, :project_id => 1, :from => '2012-06-15', :to => '2012-06-16', :sort => 'spent_on'
506 get :index, :project_id => 1,
507 :f => ['spent_on'],
508 :op => {'spent_on' => '><'},
509 :v => {'spent_on' => ['2012-06-15', '2012-06-16']},
510 :sort => 'spent_on'
585 assert_response :success
511 assert_response :success
586 assert_equal [t3, t1, t2], assigns(:entries)
512 assert_equal [t3, t1, t2], assigns(:entries)
587 end
513 end
General Comments 0
You need to be logged in to leave comments. Login now