Adds TimeEntryQuery for listing time entries.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10967 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
10998c9bae
commit
f8895a7cdd
|
@ -36,24 +36,14 @@ class TimelogController < ApplicationController
|
||||||
include TimelogHelper
|
include TimelogHelper
|
||||||
helper :custom_fields
|
helper :custom_fields
|
||||||
include CustomFieldsHelper
|
include CustomFieldsHelper
|
||||||
|
helper :queries
|
||||||
|
|
||||||
def index
|
def index
|
||||||
sort_init 'spent_on', 'desc'
|
@query = TimeEntryQuery.build_from_params(params, :name => '_')
|
||||||
sort_update 'spent_on' => ['spent_on', "#{TimeEntry.table_name}.created_on"],
|
scope = time_entry_scope
|
||||||
'user' => 'user_id',
|
|
||||||
'activity' => 'activity_id',
|
|
||||||
'project' => "#{Project.table_name}.name",
|
|
||||||
'issue' => 'issue_id',
|
|
||||||
'hours' => 'hours'
|
|
||||||
|
|
||||||
retrieve_date_range
|
sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
|
||||||
|
sort_update(@query.sortable_columns)
|
||||||
scope = TimeEntry.visible.spent_between(@from, @to)
|
|
||||||
if @issue
|
|
||||||
scope = scope.on_issue(@issue)
|
|
||||||
elsif @project
|
|
||||||
scope = scope.on_project(@project, Setting.display_subprojects_issues?)
|
|
||||||
end
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
|
@ -100,8 +90,10 @@ class TimelogController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def report
|
def report
|
||||||
retrieve_date_range
|
@query = TimeEntryQuery.build_from_params(params, :name => '_')
|
||||||
@report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], @from, @to)
|
scope = time_entry_scope
|
||||||
|
|
||||||
|
@report = Redmine::Helpers::TimeReport.new(@project, @issue, params[:criteria], params[:columns], scope)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { render :layout => !request.xhr? }
|
format.html { render :layout => !request.xhr? }
|
||||||
|
@ -291,6 +283,17 @@ private
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the TimeEntry scope for index and report actions
|
||||||
|
def time_entry_scope
|
||||||
|
scope = TimeEntry.visible.where(@query.statement)
|
||||||
|
if @issue
|
||||||
|
scope = scope.on_issue(@issue)
|
||||||
|
elsif @project
|
||||||
|
scope = scope.on_project(@project, Setting.display_subprojects_issues?)
|
||||||
|
end
|
||||||
|
scope
|
||||||
|
end
|
||||||
|
|
||||||
# Retrieves the date range based on predefined ranges or specific from/to param dates
|
# Retrieves the date range based on predefined ranges or specific from/to param dates
|
||||||
def retrieve_date_range
|
def retrieve_date_range
|
||||||
@free_period = false
|
@free_period = false
|
||||||
|
|
|
@ -117,7 +117,13 @@ class Query < ActiveRecord::Base
|
||||||
"><t+"=> :label_in_the_next_days,
|
"><t+"=> :label_in_the_next_days,
|
||||||
"t+" => :label_in,
|
"t+" => :label_in,
|
||||||
"t" => :label_today,
|
"t" => :label_today,
|
||||||
|
"ld" => :label_yesterday,
|
||||||
"w" => :label_this_week,
|
"w" => :label_this_week,
|
||||||
|
"lw" => :label_last_week,
|
||||||
|
"l2w" => [:label_last_n_weeks, :count => 2],
|
||||||
|
"m" => :label_this_month,
|
||||||
|
"lm" => :label_last_month,
|
||||||
|
"y" => :label_this_year,
|
||||||
">t-" => :label_less_than_ago,
|
">t-" => :label_less_than_ago,
|
||||||
"<t-" => :label_more_than_ago,
|
"<t-" => :label_more_than_ago,
|
||||||
"><t-"=> :label_in_the_past_days,
|
"><t-"=> :label_in_the_past_days,
|
||||||
|
@ -135,8 +141,8 @@ class Query < ActiveRecord::Base
|
||||||
:list_status => [ "o", "=", "!", "c", "*" ],
|
:list_status => [ "o", "=", "!", "c", "*" ],
|
||||||
:list_optional => [ "=", "!", "!*", "*" ],
|
:list_optional => [ "=", "!", "!*", "*" ],
|
||||||
:list_subprojects => [ "*", "!*", "=" ],
|
:list_subprojects => [ "*", "!*", "=" ],
|
||||||
:date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "t", "w", ">t-", "<t-", "><t-", "t-", "!*", "*" ],
|
:date => [ "=", ">=", "<=", "><", "<t+", ">t+", "><t+", "t+", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", ">t-", "<t-", "><t-", "t-", "!*", "*" ],
|
||||||
:date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "w", "!*", "*" ],
|
:date_past => [ "=", ">=", "<=", "><", ">t-", "<t-", "><t-", "t-", "t", "ld", "w", "lw", "l2w", "m", "lm", "y", "!*", "*" ],
|
||||||
:string => [ "=", "~", "!", "!~", "!*", "*" ],
|
:string => [ "=", "~", "!", "!~", "!*", "*" ],
|
||||||
:text => [ "~", "!~", "!*", "*" ],
|
:text => [ "~", "!~", "!*", "*" ],
|
||||||
:integer => [ "=", ">=", "<=", "><", "!*", "*" ],
|
:integer => [ "=", ">=", "<=", "><", "!*", "*" ],
|
||||||
|
@ -173,6 +179,11 @@ class Query < ActiveRecord::Base
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Builds a new query from the given params and attributes
|
||||||
|
def self.build_from_params(params, attributes={})
|
||||||
|
new(attributes).build_from_params(params)
|
||||||
|
end
|
||||||
|
|
||||||
def validate_query_filters
|
def validate_query_filters
|
||||||
filters.each_key do |field|
|
filters.each_key do |field|
|
||||||
if values_for(field)
|
if values_for(field)
|
||||||
|
@ -195,7 +206,7 @@ class Query < ActiveRecord::Base
|
||||||
# filter requires one or more values
|
# filter requires one or more values
|
||||||
(values_for(field) and !values_for(field).first.blank?) or
|
(values_for(field) and !values_for(field).first.blank?) or
|
||||||
# filter doesn't require any value
|
# filter doesn't require any value
|
||||||
["o", "c", "!*", "*", "t", "w"].include? operator_for(field)
|
["o", "c", "!*", "*", "t", "ld", "w", "lw", "l2w", "m", "lm", "y"].include? operator_for(field)
|
||||||
end if filters
|
end if filters
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -218,7 +229,7 @@ class Query < ActiveRecord::Base
|
||||||
|
|
||||||
# Returns a hash of localized labels for all filter operators
|
# Returns a hash of localized labels for all filter operators
|
||||||
def self.operators_labels
|
def self.operators_labels
|
||||||
operators.inject({}) {|h, operator| h[operator.first] = l(operator.last); h}
|
operators.inject({}) {|h, operator| h[operator.first] = l(*operator.last); h}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a representation of the available filters for JSON serialization
|
# Returns a representation of the available filters for JSON serialization
|
||||||
|
@ -245,7 +256,7 @@ class Query < ActiveRecord::Base
|
||||||
@all_projects_values = values
|
@all_projects_values = values
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_filter(field, operator, values)
|
def add_filter(field, operator, values=nil)
|
||||||
# values must be an array
|
# values must be an array
|
||||||
return unless values.nil? || values.is_a?(Array)
|
return unless values.nil? || values.is_a?(Array)
|
||||||
# check if field is defined as an available filter
|
# check if field is defined as an available filter
|
||||||
|
@ -612,12 +623,39 @@ class Query < ActiveRecord::Base
|
||||||
when "t"
|
when "t"
|
||||||
# = today
|
# = today
|
||||||
sql = relative_date_clause(db_table, db_field, 0, 0)
|
sql = relative_date_clause(db_table, db_field, 0, 0)
|
||||||
|
when "ld"
|
||||||
|
# = yesterday
|
||||||
|
sql = relative_date_clause(db_table, db_field, -1, -1)
|
||||||
when "w"
|
when "w"
|
||||||
# = this week
|
# = this week
|
||||||
first_day_of_week = l(:general_first_day_of_week).to_i
|
first_day_of_week = l(:general_first_day_of_week).to_i
|
||||||
day_of_week = Date.today.cwday
|
day_of_week = Date.today.cwday
|
||||||
days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
|
days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
|
||||||
sql = relative_date_clause(db_table, db_field, - days_ago, - days_ago + 6)
|
sql = relative_date_clause(db_table, db_field, - days_ago, - days_ago + 6)
|
||||||
|
when "lw"
|
||||||
|
# = last week
|
||||||
|
first_day_of_week = l(:general_first_day_of_week).to_i
|
||||||
|
day_of_week = Date.today.cwday
|
||||||
|
days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
|
||||||
|
sql = relative_date_clause(db_table, db_field, - days_ago - 7, - days_ago - 1)
|
||||||
|
when "l2w"
|
||||||
|
# = last 2 weeks
|
||||||
|
first_day_of_week = l(:general_first_day_of_week).to_i
|
||||||
|
day_of_week = Date.today.cwday
|
||||||
|
days_ago = (day_of_week >= first_day_of_week ? day_of_week - first_day_of_week : day_of_week + 7 - first_day_of_week)
|
||||||
|
sql = relative_date_clause(db_table, db_field, - days_ago - 14, - days_ago - 1)
|
||||||
|
when "m"
|
||||||
|
# = this month
|
||||||
|
date = Date.today
|
||||||
|
sql = date_clause(db_table, db_field, date.beginning_of_month, date.end_of_month)
|
||||||
|
when "lm"
|
||||||
|
# = last month
|
||||||
|
date = Date.today.prev_month
|
||||||
|
sql = date_clause(db_table, db_field, date.beginning_of_month, date.end_of_month)
|
||||||
|
when "y"
|
||||||
|
# = this year
|
||||||
|
date = Date.today
|
||||||
|
sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year)
|
||||||
when "~"
|
when "~"
|
||||||
sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
|
sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
|
||||||
when "!~"
|
when "!~"
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Redmine - project management software
|
||||||
|
# Copyright (C) 2006-2012 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
class TimeEntryQuery < Query
|
||||||
|
|
||||||
|
self.queried_class = TimeEntry
|
||||||
|
|
||||||
|
self.available_columns = [
|
||||||
|
QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
|
||||||
|
QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"]),
|
||||||
|
QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true),
|
||||||
|
QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true),
|
||||||
|
QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"),
|
||||||
|
QueryColumn.new(:comments),
|
||||||
|
QueryColumn.new(:hours, :sortable => "#{TimeEntry.table_name}.hours"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize(attributes=nil, *args)
|
||||||
|
super attributes
|
||||||
|
self.filters ||= {}
|
||||||
|
add_filter('spent_on', '*') unless filters.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def available_filters
|
||||||
|
return @available_filters if @available_filters
|
||||||
|
@available_filters = {
|
||||||
|
"spent_on" => { :type => :date_past, :order => 0 }
|
||||||
|
}
|
||||||
|
@available_filters.each do |field, options|
|
||||||
|
options[:name] ||= l(options[:label] || "field_#{field}".gsub(/_id$/, ''))
|
||||||
|
end
|
||||||
|
@available_filters
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_columns_names
|
||||||
|
@default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Accepts :from/:to params as shortcut filters
|
||||||
|
def build_from_params(params)
|
||||||
|
super
|
||||||
|
if params[:from].present? && params[:to].present?
|
||||||
|
add_filter('spent_on', '><', [params[:from], params[:to]])
|
||||||
|
elsif params[:from].present?
|
||||||
|
add_filter('spent_on', '>=', [params[:from]])
|
||||||
|
elsif params[:to].present?
|
||||||
|
add_filter('spent_on', '<=', [params[:to]])
|
||||||
|
end
|
||||||
|
self
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,42 +1,23 @@
|
||||||
<fieldset id="date-range" class="collapsible">
|
<div id="query_form_content" class="hide-when-print">
|
||||||
<legend onclick="toggleFieldset(this);"><%= l(:label_date_range) %></legend>
|
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
|
||||||
<div>
|
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
|
||||||
<p>
|
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
|
||||||
<%= label_tag "period_type_list", l(:description_date_range_list), :class => "hidden-for-sighted" %>
|
<%= render :partial => 'queries/filters', :locals => {:query => @query} %>
|
||||||
<%= radio_button_tag 'period_type', '1', !@free_period, :onclick => '$("#from,#to").attr("disabled", true);$("#period").removeAttr("disabled");', :id => "period_type_list"%>
|
</div>
|
||||||
<%= select_tag 'period', options_for_period_select(params[:period]),
|
|
||||||
:onchange => 'this.form.submit();',
|
|
||||||
:onfocus => '$("#period_type_1").attr("checked", true);',
|
|
||||||
:disabled => @free_period %>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<%= label_tag "period_type_interval", l(:description_date_range_interval), :class => "hidden-for-sighted" %>
|
|
||||||
<%= radio_button_tag 'period_type', '2', @free_period, :onclick => '$("#from,#to").removeAttr("disabled");$("#period").attr("disabled", true);', :id => "period_type_interval" %>
|
|
||||||
<%= l(:label_date_from_to,
|
|
||||||
:start => ((label_tag "from", l(:description_date_from), :class => "hidden-for-sighted") +
|
|
||||||
text_field_tag('from', @from, :size => 10, :disabled => !@free_period) + calendar_for('from')),
|
|
||||||
:end => ((label_tag "to", l(:description_date_to), :class => "hidden-for-sighted") +
|
|
||||||
text_field_tag('to', @to, :size => 10, :disabled => !@free_period) + calendar_for('to'))).html_safe %>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<p class="buttons">
|
</div>
|
||||||
|
|
||||||
|
<p class="buttons hide-when-print">
|
||||||
<%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
|
<%= link_to_function l(:button_apply), '$("#query_form").submit()', :class => 'icon icon-checked' %>
|
||||||
<%= link_to l(:button_clear), {:controller => controller_name, :action => action_name, :project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
|
<%= link_to l(:button_clear), {:project_id => @project, :issue_id => @issue}, :class => 'icon icon-reload' %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<% url_params = @free_period ? { :from => @from, :to => @to } : { :period => params[:period] } %>
|
<% query_params = params.slice(:f, :op, :v, :sort) %>
|
||||||
<ul>
|
<ul>
|
||||||
<li><%= link_to(l(:label_details), url_params.merge({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue }),
|
<li><%= link_to(l(:label_details), query_params.merge({:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue }),
|
||||||
:class => (action_name == 'index' ? 'selected' : nil)) %></li>
|
:class => (action_name == 'index' ? 'selected' : nil)) %></li>
|
||||||
<li><%= link_to(l(:label_report), url_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
|
<li><%= link_to(l(:label_report), query_params.merge({:controller => 'timelog', :action => 'report', :project_id => @project, :issue_id => @issue}),
|
||||||
:class => (action_name == 'report' ? 'selected' : nil)) %></li>
|
:class => (action_name == 'report' ? 'selected' : nil)) %></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= javascript_tag do %>
|
|
||||||
$('#from, #to').change(function(){
|
|
||||||
$('#period_type_interval').attr('checked', true); $('#from,#to').removeAttr('disabled'); $('#period').attr('disabled', true);
|
|
||||||
});
|
|
||||||
<% end %>
|
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
module Redmine
|
module Redmine
|
||||||
module Helpers
|
module Helpers
|
||||||
class TimeReport
|
class TimeReport
|
||||||
attr_reader :criteria, :columns, :from, :to, :hours, :total_hours, :periods
|
attr_reader :criteria, :columns, :hours, :total_hours, :periods
|
||||||
|
|
||||||
def initialize(project, issue, criteria, columns, from, to)
|
def initialize(project, issue, criteria, columns, time_entry_scope)
|
||||||
@project = project
|
@project = project
|
||||||
@issue = issue
|
@issue = issue
|
||||||
|
|
||||||
|
@ -30,8 +30,7 @@ module Redmine
|
||||||
@criteria = @criteria[0,3]
|
@criteria = @criteria[0,3]
|
||||||
|
|
||||||
@columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
|
@columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
|
||||||
@from = from
|
@scope = time_entry_scope
|
||||||
@to = to
|
|
||||||
|
|
||||||
run
|
run
|
||||||
end
|
end
|
||||||
|
@ -44,15 +43,9 @@ module Redmine
|
||||||
|
|
||||||
def run
|
def run
|
||||||
unless @criteria.empty?
|
unless @criteria.empty?
|
||||||
scope = TimeEntry.visible.spent_between(@from, @to)
|
|
||||||
if @issue
|
|
||||||
scope = scope.on_issue(@issue)
|
|
||||||
elsif @project
|
|
||||||
scope = scope.on_project(@project, Setting.display_subprojects_issues?)
|
|
||||||
end
|
|
||||||
time_columns = %w(tyear tmonth tweek spent_on)
|
time_columns = %w(tyear tmonth tweek spent_on)
|
||||||
@hours = []
|
@hours = []
|
||||||
scope.sum(:hours, :include => :issue, :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns).each do |hash, hours|
|
@scope.sum(:hours, :include => :issue, :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns).each do |hash, hours|
|
||||||
h = {'hours' => hours}
|
h = {'hours' => hours}
|
||||||
(@criteria + time_columns).each_with_index do |name, i|
|
(@criteria + time_columns).each_with_index do |name, i|
|
||||||
h[name] = hash[i]
|
h[name] = hash[i]
|
||||||
|
@ -73,15 +66,11 @@ module Redmine
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if @from.nil?
|
min = @hours.collect {|row| row['spent_on']}.min
|
||||||
min = @hours.collect {|row| row['spent_on']}.min
|
@from = min ? min.to_date : Date.today
|
||||||
@from = min ? min.to_date : Date.today
|
|
||||||
end
|
|
||||||
|
|
||||||
if @to.nil?
|
max = @hours.collect {|row| row['spent_on']}.max
|
||||||
max = @hours.collect {|row| row['spent_on']}.max
|
@to = max ? max.to_date : Date.today
|
||||||
@to = max ? max.to_date : Date.today
|
|
||||||
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}
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,13 @@ function toggleOperator(field) {
|
||||||
case "!*":
|
case "!*":
|
||||||
case "*":
|
case "*":
|
||||||
case "t":
|
case "t":
|
||||||
|
case "ld":
|
||||||
case "w":
|
case "w":
|
||||||
|
case "lw":
|
||||||
|
case "l2w":
|
||||||
|
case "m":
|
||||||
|
case "lm":
|
||||||
|
case "y":
|
||||||
case "o":
|
case "o":
|
||||||
case "c":
|
case "c":
|
||||||
enableValues(field, []);
|
enableValues(field, []);
|
||||||
|
|
|
@ -166,10 +166,9 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
|
||||||
assert_equal 'text/csv; header=present', @response.content_type
|
assert_equal 'text/csv; header=present', @response.content_type
|
||||||
lines = @response.body.chomp.split("\n")
|
lines = @response.body.chomp.split("\n")
|
||||||
# Headers
|
# Headers
|
||||||
assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total',
|
assert_equal 'Project,Member,Activity,2007-3,2007-4,Total', lines.first
|
||||||
lines.first
|
|
||||||
# Total row
|
# Total row
|
||||||
assert_equal 'Total,"","","","",154.25,8.65,"","",162.90', lines.last
|
assert_equal 'Total,"","",154.25,8.65,162.90', lines.last
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_report_csv_export
|
def test_report_csv_export
|
||||||
|
@ -180,10 +179,9 @@ class TimeEntryReportsControllerTest < ActionController::TestCase
|
||||||
assert_equal 'text/csv; header=present', @response.content_type
|
assert_equal 'text/csv; header=present', @response.content_type
|
||||||
lines = @response.body.chomp.split("\n")
|
lines = @response.body.chomp.split("\n")
|
||||||
# Headers
|
# Headers
|
||||||
assert_equal 'Project,Member,Activity,2007-1,2007-2,2007-3,2007-4,2007-5,2007-6,Total',
|
assert_equal 'Project,Member,Activity,2007-3,2007-4,Total', lines.first
|
||||||
lines.first
|
|
||||||
# Total row
|
# Total row
|
||||||
assert_equal 'Total,"","","","",154.25,8.65,"","",162.90', lines.last
|
assert_equal 'Total,"","",154.25,8.65,162.90', lines.last
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_csv_big_5
|
def test_csv_big_5
|
||||||
|
|
|
@ -430,14 +430,26 @@ class TimelogControllerTest < ActionController::TestCase
|
||||||
assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
|
assert_equal [1, 3], assigns(:entries).collect(&:project_id).uniq.sort
|
||||||
assert_not_nil assigns(:total_hours)
|
assert_not_nil assigns(:total_hours)
|
||||||
assert_equal "162.90", "%.2f" % assigns(:total_hours)
|
assert_equal "162.90", "%.2f" % assigns(:total_hours)
|
||||||
# display all time by default
|
|
||||||
assert_nil assigns(:from)
|
|
||||||
assert_nil assigns(:to)
|
|
||||||
assert_tag :form,
|
assert_tag :form,
|
||||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_index_at_project_level_with_date_range
|
def test_index_at_project_level_with_date_range
|
||||||
|
get :index, :project_id => 'ecookbook',
|
||||||
|
:f => ['spent_on'],
|
||||||
|
:op => {'spent_on' => '><'},
|
||||||
|
:v => {'spent_on' => ['2007-03-20', '2007-04-30']}
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'index'
|
||||||
|
assert_not_nil assigns(:entries)
|
||||||
|
assert_equal 3, assigns(:entries).size
|
||||||
|
assert_not_nil assigns(:total_hours)
|
||||||
|
assert_equal "12.90", "%.2f" % assigns(:total_hours)
|
||||||
|
assert_tag :form,
|
||||||
|
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_index_at_project_level_with_date_range_using_from_and_to_params
|
||||||
get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
|
get :index, :project_id => 'ecookbook', :from => '2007-03-20', :to => '2007-04-30'
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'index'
|
assert_template 'index'
|
||||||
|
@ -445,116 +457,23 @@ class TimelogControllerTest < ActionController::TestCase
|
||||||
assert_equal 3, assigns(:entries).size
|
assert_equal 3, assigns(:entries).size
|
||||||
assert_not_nil assigns(:total_hours)
|
assert_not_nil assigns(:total_hours)
|
||||||
assert_equal "12.90", "%.2f" % assigns(:total_hours)
|
assert_equal "12.90", "%.2f" % assigns(:total_hours)
|
||||||
assert_equal '2007-03-20'.to_date, assigns(:from)
|
|
||||||
assert_equal '2007-04-30'.to_date, assigns(:to)
|
|
||||||
assert_tag :form,
|
assert_tag :form,
|
||||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_index_at_project_level_with_period
|
def test_index_at_project_level_with_period
|
||||||
get :index, :project_id => 'ecookbook', :period => '7_days'
|
get :index, :project_id => 'ecookbook',
|
||||||
|
:f => ['spent_on'],
|
||||||
|
:op => {'spent_on' => '>t-'},
|
||||||
|
:v => {'spent_on' => ['7']}
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'index'
|
assert_template 'index'
|
||||||
assert_not_nil assigns(:entries)
|
assert_not_nil assigns(:entries)
|
||||||
assert_not_nil assigns(:total_hours)
|
assert_not_nil assigns(:total_hours)
|
||||||
assert_equal Date.today - 7, assigns(:from)
|
|
||||||
assert_equal Date.today, assigns(:to)
|
|
||||||
assert_tag :form,
|
assert_tag :form,
|
||||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_index_one_day
|
|
||||||
get :index, :project_id => 'ecookbook', :from => "2007-03-23", :to => "2007-03-23"
|
|
||||||
assert_response :success
|
|
||||||
assert_template 'index'
|
|
||||||
assert_not_nil assigns(:total_hours)
|
|
||||||
assert_equal "4.25", "%.2f" % assigns(:total_hours)
|
|
||||||
assert_tag :form,
|
|
||||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_from_a_date
|
|
||||||
get :index, :project_id => 'ecookbook', :from => "2007-03-23", :to => ""
|
|
||||||
assert_equal '2007-03-23'.to_date, assigns(:from)
|
|
||||||
assert_nil assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_to_a_date
|
|
||||||
get :index, :project_id => 'ecookbook', :from => "", :to => "2007-03-23"
|
|
||||||
assert_nil assigns(:from)
|
|
||||||
assert_equal '2007-03-23'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_today
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'today'
|
|
||||||
assert_equal '2011-12-15'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-15'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_yesterday
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'yesterday'
|
|
||||||
assert_equal '2011-12-14'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-14'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_current_week
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'current_week'
|
|
||||||
assert_equal '2011-12-12'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-18'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_last_week
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'last_week'
|
|
||||||
assert_equal '2011-12-05'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-11'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_last_2_week
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'last_2_weeks'
|
|
||||||
assert_equal '2011-11-28'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-11'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_7_days
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => '7_days'
|
|
||||||
assert_equal '2011-12-08'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-15'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_current_month
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'current_month'
|
|
||||||
assert_equal '2011-12-01'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-31'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_last_month
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'last_month'
|
|
||||||
assert_equal '2011-11-01'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-11-30'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_30_days
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => '30_days'
|
|
||||||
assert_equal '2011-11-15'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-15'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_current_year
|
|
||||||
Date.stubs(:today).returns('2011-12-15'.to_date)
|
|
||||||
get :index, :period => 'current_year'
|
|
||||||
assert_equal '2011-01-01'.to_date, assigns(:from)
|
|
||||||
assert_equal '2011-12-31'.to_date, assigns(:to)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_index_at_issue_level
|
def test_index_at_issue_level
|
||||||
get :index, :issue_id => 1
|
get :index, :issue_id => 1
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
@ -577,11 +496,18 @@ class TimelogControllerTest < ActionController::TestCase
|
||||||
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)
|
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)
|
||||||
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)
|
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)
|
||||||
|
|
||||||
get :index, :project_id => 1, :from => '2012-06-15', :to => '2012-06-16'
|
get :index, :project_id => 1,
|
||||||
|
:f => ['spent_on'],
|
||||||
|
:op => {'spent_on' => '><'},
|
||||||
|
:v => {'spent_on' => ['2012-06-15', '2012-06-16']}
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_equal [t2, t1, t3], assigns(:entries)
|
assert_equal [t2, t1, t3], assigns(:entries)
|
||||||
|
|
||||||
get :index, :project_id => 1, :from => '2012-06-15', :to => '2012-06-16', :sort => 'spent_on'
|
get :index, :project_id => 1,
|
||||||
|
:f => ['spent_on'],
|
||||||
|
:op => {'spent_on' => '><'},
|
||||||
|
:v => {'spent_on' => ['2012-06-15', '2012-06-16']},
|
||||||
|
:sort => 'spent_on'
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_equal [t3, t1, t2], assigns(:entries)
|
assert_equal [t3, t1, t2], assigns(:entries)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue