Merge pull request #50 from finnlabs/feature/houndci-config-ruby-style

Add Hound/Rubocop config; Make Ruby style consistent
pull/6827/head
Alex Coles 10 years ago
commit bdd4e14cb5
  1. 3
      .hound.yml
  2. 265
      .rubocop.yml
  3. 69
      app/controllers/cost_reports_controller.rb
  4. 38
      app/helpers/reporting_helper.rb
  5. 6
      app/models/cost_query.rb
  6. 7
      app/models/cost_query/custom_field_mixin.rb
  7. 3
      app/models/cost_query/filter/activity_id.rb
  8. 2
      app/models/cost_query/filter/category_id.rb
  9. 2
      app/models/cost_query/filter/cost_object_id.rb
  10. 2
      app/models/cost_query/filter/cost_type_id.rb
  11. 2
      app/models/cost_query/filter/created_on.rb
  12. 2
      app/models/cost_query/filter/fixed_version_id.rb
  13. 2
      app/models/cost_query/filter/no_filter.rb
  14. 3
      app/models/cost_query/filter/overridden_costs.rb
  15. 12
      app/models/cost_query/filter/permission_filter.rb
  16. 2
      app/models/cost_query/filter/priority_id.rb
  17. 8
      app/models/cost_query/filter/project_id.rb
  18. 4
      app/models/cost_query/filter/status_id.rb
  19. 2
      app/models/cost_query/filter/tmonth.rb
  20. 2
      app/models/cost_query/filter/tweek.rb
  21. 2
      app/models/cost_query/filter/tyear.rb
  22. 2
      app/models/cost_query/filter/type_id.rb
  23. 2
      app/models/cost_query/filter/updated_on.rb
  24. 4
      app/models/cost_query/filter/user_id.rb
  25. 7
      app/models/cost_query/filter/work_package_id.rb
  26. 2
      app/models/cost_query/group_by/sql_aggregation.rb
  27. 8
      app/models/cost_query/operator.rb
  28. 16
      app/models/cost_query/sql_statement.rb
  29. 2
      features/step_definitions/custom_steps.rb
  30. 4
      features/step_definitions/disabled_scenarios.rb
  31. 34
      lib/open_project/reporting/engine.rb
  32. 2
      lib/open_project/reporting/hooks.rb
  33. 16
      lib/open_project/reporting/patches/costlog_controller_patch.rb
  34. 14
      lib/open_project/reporting/patches/timelog_controller_patch.rb
  35. 48
      lib/widget/entry_table.rb
  36. 4
      lib/widget/settings_patch.rb
  37. 18
      lib/widget/simple_table.rb
  38. 2
      lib/widget/sortable_init.rb
  39. 4
      spec/controllers/cost_reports_controller_spec.rb
  40. 4
      spec/factories/cost_query_factory.rb
  41. 28
      spec/models/cost_query/chaining_spec.rb
  42. 8
      spec/models/cost_query/cost_query_spec.rb
  43. 166
      spec/models/cost_query/filter_spec.rb
  44. 24
      spec/models/cost_query/group_by_spec.rb
  45. 12
      spec/models/cost_query/integration_spec.rb
  46. 68
      spec/models/cost_query/operator_spec.rb
  47. 6
      spec/models/cost_query/result_spec.rb
  48. 2
      spec/models/cost_query/validation_spec.rb
  49. 2
      spec/models/cost_query/walker_spec.rb
  50. 8
      spec/support/plugin_spec_helper.rb
  51. 6
      spec/support/project_helper.rb
  52. 2
      spec/support/query_helper.rb

@ -0,0 +1,3 @@
ruby:
enabled: true
config_file: .rubocop.yml

@ -0,0 +1,265 @@
AllCops:
Exclude:
- *.gemspec
AccessorMethodName:
Enabled: false
ActionFilter:
Enabled: false
Alias:
Enabled: false
AndOr:
Enabled: false
ArrayJoin:
Enabled: false
AsciiComments:
Enabled: false
AsciiIdentifiers:
Enabled: false
Attr:
Enabled: false
BlockNesting:
Enabled: false
Blocks:
Enabled: false
CaseEquality:
Enabled: false
CharacterLiteral:
Enabled: false
ClassAndModuleChildren:
Enabled: false
ClassLength:
Enabled: false
ClassVars:
Enabled: false
CollectionMethods:
PreferredMethods:
find: detect
reduce: inject
collect: map
find_all: select
ColonMethodCall:
Enabled: false
CommentAnnotation:
Enabled: false
CyclomaticComplexity:
Enabled: false
Delegate:
Enabled: false
DeprecatedHashMethods:
Enabled: false
Documentation:
Enabled: false
DotPosition:
EnforcedStyle: leading
DoubleNegation:
Enabled: false
EachWithObject:
Enabled: false
EmptyLiteral:
Enabled: false
Encoding:
Enabled: false
EvenOdd:
Enabled: false
FileName:
Enabled: false
FlipFlop:
Enabled: false
FormatString:
Enabled: false
GlobalVars:
Enabled: false
GuardClause:
Enabled: false
IfUnlessModifier:
Enabled: false
IfWithSemicolon:
Enabled: false
InlineComment:
Enabled: false
Lambda:
Enabled: false
LambdaCall:
Enabled: false
LineEndConcatenation:
Enabled: false
LineLength:
Max: 100
MethodLength:
Enabled: false
ModuleFunction:
Enabled: false
NegatedIf:
Enabled: false
NegatedWhile:
Enabled: false
Next:
Enabled: false
NilComparison:
Enabled: false
Not:
Enabled: false
NumericLiterals:
Enabled: false
OneLineConditional:
Enabled: false
OpMethod:
Enabled: false
ParameterLists:
Enabled: false
PercentLiteralDelimiters:
Enabled: false
PerlBackrefs:
Enabled: false
PredicateName:
NamePrefixBlacklist:
- is_
Proc:
Enabled: false
RaiseArgs:
Enabled: false
RegexpLiteral:
Enabled: false
SelfAssignment:
Enabled: false
SingleLineBlockParams:
Enabled: false
SingleLineMethods:
Enabled: false
SignalException:
Enabled: false
SpecialGlobalVars:
Enabled: false
StringLiterals:
EnforcedStyle: single_quotes
VariableInterpolation:
Enabled: false
TrailingComma:
Enabled: false
TrivialAccessors:
Enabled: false
VariableInterpolation:
Enabled: false
WhenThen:
Enabled: false
WhileUntilModifier:
Enabled: false
WordArray:
Enabled: false
# Lint
AmbiguousOperator:
Enabled: false
AmbiguousRegexpLiteral:
Enabled: false
AssignmentInCondition:
Enabled: false
ConditionPosition:
Enabled: false
DeprecatedClassMethods:
Enabled: false
ElseLayout:
Enabled: false
HandleExceptions:
Enabled: false
InvalidCharacterLiteral:
Enabled: false
LiteralInCondition:
Enabled: false
LiteralInInterpolation:
Enabled: false
Loop:
Enabled: false
ParenthesesAsGroupedExpression:
Enabled: false
RequireParentheses:
Enabled: false
UnderscorePrefixedVariableName:
Enabled: false
Void:
Enabled: false

@ -18,17 +18,15 @@
#++ #++
class CostReportsController < ApplicationController class CostReportsController < ApplicationController
rescue_from Exception do |exception| rescue_from Exception do |exception|
session.delete(CostQuery.name.underscore.to_sym) session.delete(CostQuery.name.underscore.to_sym)
raise exception raise exception
end end
rescue_from ActiveRecord::RecordNotFound do |exception| rescue_from ActiveRecord::RecordNotFound do |_exception|
render_404 render_404
end end
Widget::Base.dont_cache! Widget::Base.dont_cache!
before_filter :check_cache before_filter :check_cache
@ -38,8 +36,8 @@ class CostReportsController < ApplicationController
include Report::Controller include Report::Controller
before_filter :set_cost_types # has to be set AFTER the Report::Controller filters run before_filter :set_cost_types # has to be set AFTER the Report::Controller filters run
verify :method => :delete, :only => %w[delete] verify method: :delete, only: %w[delete]
verify :method => :post, :only => %w[create update rename] verify method: :post, only: %w[create update rename]
helper_method :cost_types helper_method :cost_types
helper_method :cost_type helper_method :cost_type
@ -53,7 +51,7 @@ class CostReportsController < ApplicationController
# Checks if custom fields have been updated, added or removed since we # Checks if custom fields have been updated, added or removed since we
# last saw them, to rebuild the filters and group bys. # last saw them, to rebuild the filters and group bys.
# Called once per request. # Called once per request.
def check_cache(force_update=false) def check_cache(force_update = false)
custom_fields_updated_on = WorkPackageCustomField.maximum(:updated_at) custom_fields_updated_on = WorkPackageCustomField.maximum(:updated_at)
custom_fields_id_sum = WorkPackageCustomField.sum(:id) + WorkPackageCustomField.count custom_fields_id_sum = WorkPackageCustomField.sum(:id) + WorkPackageCustomField.count
@ -81,13 +79,13 @@ class CostReportsController < ApplicationController
respond_to do |format| respond_to do |format|
format.html { format.html {
session[report_engine.name.underscore.to_sym].try(:delete, :name) session[report_engine.name.underscore.to_sym].try(:delete, :name)
render :action => "index" render action: 'index'
} }
end unless performed? end unless performed?
end end
def drill_down def drill_down
redirect_to :action => :index redirect_to action: :index
end end
## ##
@ -106,12 +104,12 @@ class CostReportsController < ApplicationController
## ##
# Set a default query to cut down initial load time # Set a default query to cut down initial load time
def default_filter_parameters def default_filter_parameters
{:operators => {:user_id => "=", :spent_on => ">d"}, { operators: { user_id: '=', spent_on: '>d' },
:values => {:user_id => [User.current.id], :spent_on => [30.days.ago.strftime('%Y-%m-%d')]} values: { user_id: [User.current.id], spent_on: [30.days.ago.strftime('%Y-%m-%d')] }
}.tap do |hash| }.tap do |hash|
if @project if @project
hash[:operators].merge! :project_id => "=" hash[:operators].merge! project_id: '='
hash[:values].merge! :project_id => [@project.id] hash[:values].merge! project_id: [@project.id]
end end
end end
end end
@ -119,7 +117,7 @@ class CostReportsController < ApplicationController
## ##
# Set a default query to cut down initial load time # Set a default query to cut down initial load time
def default_group_parameters def default_group_parameters
{:columns => [:week], :rows => []}.tap do |h| { columns: [:week], rows: [] }.tap do |h|
if @project if @project
h[:rows] << :work_package_id h[:rows] << :work_package_id
else else
@ -133,8 +131,8 @@ class CostReportsController < ApplicationController
def ensure_project_scope!(filters) def ensure_project_scope!(filters)
return unless ensure_project_scope? return unless ensure_project_scope?
if @project if @project
filters[:operators].merge! :project_id => "=" filters[:operators].merge! project_id: '='
filters[:values].merge! :project_id => @project.id.to_s filters[:values].merge! project_id: @project.id.to_s
else else
filters[:operators].delete :project_id filters[:operators].delete :project_id
filters[:values].delete :project_id filters[:values].delete :project_id
@ -157,11 +155,11 @@ class CostReportsController < ApplicationController
# sets the @unit_id -> this is used in the index for determining the active unit tab # sets the @unit_id -> this is used in the index for determining the active unit tab
def set_unit def set_unit
@unit_id = if set_unit? @unit_id = if set_unit?
params[:unit].to_i params[:unit].to_i
elsif @query.present? elsif @query.present?
cost_type_filter = @query.filters.detect{ |f| f.is_a?(CostQuery::Filter::CostTypeId) } cost_type_filter = @query.filters.detect { |f| f.is_a?(CostQuery::Filter::CostTypeId) }
cost_type_filter.values.first.to_i if cost_type_filter cost_type_filter.values.first.to_i if cost_type_filter
end end
@unit_id = 0 unless @cost_types.include? @unit_id @unit_id = 0 unless @cost_types.include? @unit_id
@ -171,7 +169,7 @@ class CostReportsController < ApplicationController
# sets the @cost_type -> this is used to select the proper units for display # sets the @cost_type -> this is used to select the proper units for display
def set_cost_type def set_cost_type
if @unit_id != 0 && @query if @unit_id != 0 && @query
@query.filter :cost_type_id, :operator => '=', :value => @unit_id.to_s, :display => false @query.filter :cost_type_id, operator: '=', value: @unit_id.to_s, display: false
@cost_type = CostType.find(@unit_id) if @unit_id > 0 @cost_type = CostType.find(@unit_id) if @unit_id > 0
end end
end end
@ -179,7 +177,7 @@ class CostReportsController < ApplicationController
# set the @cost_types -> this is used to determine which tabs to display # set the @cost_types -> this is used to determine which tabs to display
def set_active_cost_types def set_active_cost_types
unless session[:report] && (@cost_types = session[:report][:filters][:values][:cost_type_id].try(:collect, &:to_i)) unless session[:report] && (@cost_types = session[:report][:filters][:values][:cost_type_id].try(:collect, &:to_i))
relevant_cost_types = CostType.find(:all, :select => "id", :order => "id ASC").select do |t| relevant_cost_types = CostType.find(:all, select: 'id', order: 'id ASC').select do |t|
t.cost_entries.count > 0 t.cost_entries.count > 0
end.collect(&:id) end.collect(&:id)
@cost_types = [-1, 0, *relevant_cost_types] @cost_types = [-1, 0, *relevant_cost_types]
@ -215,7 +213,7 @@ class CostReportsController < ApplicationController
if report.project.present? if report.project.present?
options = {} options = {}
else else
options = {:global => true} options = { global: true }
end end
case action case action
@ -242,37 +240,38 @@ class CostReportsController < ApplicationController
def public_queries def public_queries
if @project if @project
CostQuery.find(:all, CostQuery.find(:all,
:conditions => ["is_public = ? AND (project_id IS NULL OR project_id = ?)", conditions: ['is_public = ? AND (project_id IS NULL OR project_id = ?)',
true, @project], true, @project],
:order => "name ASC") order: 'name ASC')
else else
CostQuery.find(:all, CostQuery.find(:all,
:conditions => ["is_public = ? AND project_id IS NULL", conditions: ['is_public = ? AND project_id IS NULL',
true], true],
:order => "name ASC") order: 'name ASC')
end end
end end
def private_queries def private_queries
if @project if @project
CostQuery.find(:all, CostQuery.find(:all,
:conditions => ["user_id = ? AND is_public = ? AND (project_id IS NULL OR project_id = ?)", conditions: ['user_id = ? AND is_public = ? AND (project_id IS NULL OR project_id = ?)',
current_user, false, @project], current_user, false, @project],
:order => "name ASC") order: 'name ASC')
else else
CostQuery.find(:all, CostQuery.find(:all,
:conditions => ["user_id = ? AND is_public = ? AND project_id IS NULL", conditions: ['user_id = ? AND is_public = ? AND project_id IS NULL',
current_user, false], current_user, false],
:order => "name ASC") order: 'name ASC')
end end
end end
def display_report_list def display_report_list
report_type = params[:report_type] || :public report_type = params[:report_type] || :public
render :partial => "report_list", :locals => { :report_type => report_type }, :layout => !request.xhr? render partial: 'report_list', locals: { report_type: report_type }, layout: !request.xhr?
end end
private private
def find_optional_user def find_optional_user
@current_user = User.current || User.anonymous @current_user = User.current || User.anonymous
end end

@ -40,7 +40,7 @@ module ReportingHelper
def label_for(field) def label_for(field)
name = field.to_s name = field.to_s
if name.starts_with?("label") if name.starts_with?('label')
return I18n.t(field) return I18n.t(field)
end end
name = name.camelcase name = name.camelcase
@ -50,15 +50,15 @@ module ReportingHelper
CostQuery::GroupBy.const_defined? name CostQuery::GroupBy.const_defined? name
CostQuery::GroupBy.const_get(name).label CostQuery::GroupBy.const_get(name).label
else else
#note that using WorkPackage.human_attribute_name relies on the attribute # note that using WorkPackage.human_attribute_name relies on the attribute
#being an work_package attribute or a general attribute for all models whicht might not # being an work_package attribute or a general attribute for all models whicht might not
#be the case but so far I have only seen the "comments" attribute in reports # be the case but so far I have only seen the "comments" attribute in reports
WorkPackage.human_attribute_name(field) WorkPackage.human_attribute_name(field)
end end
end end
def debug_fields(result, prefix = ", ") def debug_fields(result, prefix = ', ')
prefix << result.fields.inspect << ", " << result.important_fields.inspect << ', ' << result.key.inspect if params[:debug] prefix << result.fields.inspect << ', ' << result.important_fields.inspect << ', ' << result.key.inspect if params[:debug]
end end
def month_name(index) def month_name(index)
@ -68,12 +68,12 @@ module ReportingHelper
# ======================= SHARED CODE END # ======================= SHARED CODE END
def show_field(key, value) def show_field(key, value)
@show_row ||= Hash.new { |h,k| h[k] = {}} @show_row ||= Hash.new { |h, k| h[k] = {} }
@show_row[key][value] ||= field_representation_map(key, value) @show_row[key][value] ||= field_representation_map(key, value)
end end
def raw_field(key, value) def raw_field(key, value)
@raw_row ||= Hash.new { |h,k| h[k] = {}} @raw_row ||= Hash.new { |h, k| h[k] = {} }
@raw_row[key][value] ||= field_sort_map(key, value) @raw_row[key][value] ||= field_sort_map(key, value)
end end
@ -104,18 +104,18 @@ module ReportingHelper
when :week then "#{l(:label_week)} #%s" % value.to_i.modulo(100) when :week then "#{l(:label_week)} #%s" % value.to_i.modulo(100)
when :priority_id then h(IssuePriority.find(value.to_i).name) when :priority_id then h(IssuePriority.find(value.to_i).name)
when :fixed_version_id then h(Version.find(value.to_i).name) when :fixed_version_id then h(Version.find(value.to_i).name)
when :singleton_value then "" when :singleton_value then ''
when :status_id then h(Status.find(value.to_i).name) when :status_id then h(Status.find(value.to_i).name)
else h(value.to_s) else h(value.to_s)
end end
end end
def field_sort_map(key, value) def field_sort_map(key, value)
return "" if value.blank? return '' if value.blank?
case key.to_sym case key.to_sym
when :work_package_id, :tweek, :tmonth, :week then value.to_i when :work_package_id, :tweek, :tmonth, :week then value.to_i
when :spent_on then value.to_date.mjd when :spent_on then value.to_date.mjd
else h(field_representation_map(key, value).gsub(/<\/?[^>]*>/, "")) else h(field_representation_map(key, value).gsub(/<\/?[^>]*>/, ''))
end end
end end
@ -130,7 +130,7 @@ module ReportingHelper
end end
def set_filter_options(struct, key, value) def set_filter_options(struct, key, value)
struct[:operators][key] = "=" struct[:operators][key] = '='
struct[:values][key] = value.to_s struct[:values][key] = value.to_s
end end
@ -138,10 +138,10 @@ module ReportingHelper
tabs = cost_types.to_a tabs = cost_types.to_a
tabs.delete 0 # remove money from list tabs.delete 0 # remove money from list
tabs.unshift 0 # add money as first tab tabs.unshift 0 # add money as first tab
tabs.map {|cost_type_id| [cost_type_id, cost_type_label(cost_type_id)] } tabs.map { |cost_type_id| [cost_type_id, cost_type_label(cost_type_id)] }
end end
def cost_type_label(cost_type_id, cost_type_inst = nil, plural = true) def cost_type_label(cost_type_id, cost_type_inst = nil, _plural = true)
case cost_type_id case cost_type_id
when -1 then l(:caption_labor) when -1 then l(:caption_labor)
when 0 then l(:label_money) when 0 then l(:label_money)
@ -151,7 +151,7 @@ module ReportingHelper
def link_to_details(result) def link_to_details(result)
return '' # unless result.respond_to? :fields # uncomment to display return '' # unless result.respond_to? :fields # uncomment to display
session_filter = {:operators => session[:report][:filters][:operators].dup, :values => session[:report][:filters][:values].dup } session_filter = { operators: session[:report][:filters][:operators].dup, values: session[:report][:filters][:values].dup }
filters = result.fields.inject session_filter do |struct, (key, value)| filters = result.fields.inject session_filter do |struct, (key, value)|
key = key.to_sym key = key.to_sym
case key case key
@ -166,14 +166,14 @@ module ReportingHelper
end end
struct struct
end end
options = { :fields => filters[:operators].keys, :set_filter => 1, :action => :drill_down } options = { fields: filters[:operators].keys, set_filter: 1, action: :drill_down }
link_to '[+]', filters.merge(options), :class => 'drill_down', :title => l(:description_drill_down) link_to '[+]', filters.merge(options), class: 'drill_down', title: l(:description_drill_down)
end end
## ##
# Create the appropriate action for an entry with the type of log to use # Create the appropriate action for an entry with the type of log to use
def action_for(result, options = {}) def action_for(result, options = {})
options.merge :controller => result.fields['type'] == 'TimeEntry' ? 'timelog' : 'costlog', :id => result.fields['id'].to_i options.merge controller: result.fields['type'] == 'TimeEntry' ? 'timelog' : 'costlog', id: result.fields['id'].to_i
end end
## ##
@ -187,7 +187,7 @@ module ReportingHelper
# For a given row, determine how to render it's contents according to usability and # For a given row, determine how to render it's contents according to usability and
# localization rules # localization rules
def show_row(row) def show_row(row)
row_text = link_to_details(row) << row.render { |k,v| show_field(k,v) } row_text = link_to_details(row) << row.render { |k, v| show_field(k, v) }
row_text.html_safe row_text.html_safe
end end

@ -25,9 +25,9 @@ class CostQuery < Report
CostQuery.update_all ['user_id = ?', DeletedUser.first.id], ['user_id = ?', user.id] CostQuery.update_all ['user_id = ?', DeletedUser.first.id], ['user_id = ?', user.id]
max_query_id = 0 max_query_id = 0
while((current_queries = CostQuery.all(:limit => 1000, while((current_queries = CostQuery.all(limit: 1000,
:conditions => ["id > ?", max_query_id], conditions: ["id > ?", max_query_id],
:order => "id ASC")).size > 0) do order: "id ASC")).size > 0) do
current_queries.each do |query| current_queries.each do |query|
serialized = query.serialized serialized = query.serialized

@ -44,7 +44,7 @@ module CostQuery::CustomFieldMixin
end end
def generate_subclasses def generate_subclasses
WorkPackageCustomField.all(:conditions => "field_format in ('#{SQL_TYPES.keys.join('\',\'')}')").map do |field| WorkPackageCustomField.all(conditions: "field_format in ('#{SQL_TYPES.keys.join('\',\'')}')").map do |field|
class_name = "CustomField#{field.id}" class_name = "CustomField#{field.id}"
parent.send(:remove_const, class_name) if parent.const_defined? class_name parent.send(:remove_const, class_name) if parent.const_defined? class_name
parent.const_set class_name, Class.new(self) parent.const_set class_name, Class.new(self)
@ -59,7 +59,7 @@ module CostQuery::CustomFieldMixin
def on_prepare(&block) def on_prepare(&block)
return factory.on_prepare unless factory? return factory.on_prepare unless factory?
@on_prepare = block if block @on_prepare = block if block
@on_prepare ||= proc { } @on_prepare ||= proc {}
@on_prepare @on_prepare
end end
@ -76,7 +76,7 @@ module CostQuery::CustomFieldMixin
@class_name = class_name @class_name = class_name
dont_inherit :group_fields dont_inherit :group_fields
db_field table_name db_field table_name
join_table (<<-SQL % [CustomValue.table_name, table_name, field.id, field.name, SQL_TYPES[field.field_format]]).gsub(/^ /, "") join_table (<<-SQL % [CustomValue.table_name, table_name, field.id, field.name, SQL_TYPES[field.field_format]]).gsub(/^ /, '')
-- BEGIN Custom Field Join: "%4$s" -- BEGIN Custom Field Join: "%4$s"
LEFT OUTER JOIN ( LEFT OUTER JOIN (
\tSELECT \tSELECT
@ -100,5 +100,4 @@ module CostQuery::CustomFieldMixin
fail "Only subclasses of #{self} should be instanciated." if factory? fail "Only subclasses of #{self} should be instanciated." if factory?
super super
end end
end end

@ -18,12 +18,11 @@
#++ #++
class CostQuery::Filter::ActivityId < Report::Filter::Base class CostQuery::Filter::ActivityId < Report::Filter::Base
def self.label def self.label
TimeEntry.human_attribute_name(:activity) TimeEntry.human_attribute_name(:activity)
end end
def self.available_values(*) def self.available_values(*)
TimeEntryActivity.find(:all, :order => 'name').map { |a| [a.name, a.id] } TimeEntryActivity.find(:all, order: 'name').map { |a| [a.name, a.id] }
end end
end end

@ -27,7 +27,7 @@ class CostQuery::Filter::CategoryId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
categories = Category.find :all, :conditions => {:project_id => Project.visible.map{|p| p.id}} categories = Category.find :all, conditions: { project_id: Project.visible.map(&:id) }
categories.map { |c| ["#{c.project.name} - #{c.name} ", c.id] }.sort_by { |a| a.first.to_s + a.second.to_s } categories.map { |c| ["#{c.project.name} - #{c.name} ", c.id] }.sort_by { |a| a.first.to_s + a.second.to_s }
end end
end end

@ -26,6 +26,6 @@ class CostQuery::Filter::CostObjectId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
([[l(:caption_labor), -1]] + CostObject.find(:all, :order => 'name').map { |t| [t.name, t.id] }) ([[l(:caption_labor), -1]] + CostObject.find(:all, order: 'name').map { |t| [t.name, t.id] })
end end
end end

@ -39,6 +39,6 @@ class CostQuery::Filter::CostTypeId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
([[::I18n.t(:caption_labor), -1]] + CostType.find(:all, :order => 'name').map { |t| [t.name, t.id] }) ([[::I18n.t(:caption_labor), -1]] + CostType.find(:all, order: 'name').map { |t| [t.name, t.id] })
end end
end end

@ -18,7 +18,7 @@
#++ #++
class CostQuery::Filter::CreatedOn < Report::Filter::Base class CostQuery::Filter::CreatedOn < Report::Filter::Base
db_field "entries.created_on" db_field 'entries.created_on'
use :time_operators use :time_operators
def self.label def self.label

@ -27,7 +27,7 @@ class CostQuery::Filter::FixedVersionId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
versions = Version.find :all, :conditions => {:project_id => Project.visible.map{|p| p.id}} versions = Version.find :all, conditions: { project_id: Project.visible.map(&:id) }
versions.map { |a| ["#{a.project.name} - #{a.name}", a.id] }.sort_by { |a| a.first.to_s + a.second.to_s } versions.map { |a| ["#{a.project.name} - #{a.name}", a.id] }.sort_by { |a| a.first.to_s + a.second.to_s }
end end
end end

@ -18,7 +18,7 @@
#++ #++
class CostQuery::Filter::NoFilter < Report::Filter::NoFilter class CostQuery::Filter::NoFilter < Report::Filter::NoFilter
table_name "entries" table_name 'entries'
dont_display! dont_display!
singleton singleton

@ -18,13 +18,12 @@
#++ #++
class CostQuery::Filter::OverriddenCosts < Report::Filter::Base class CostQuery::Filter::OverriddenCosts < Report::Filter::Base
def self.label def self.label
CostEntry.human_attribute_name(:overridden_costs) CostEntry.human_attribute_name(:overridden_costs)
end end
def self.available_operators def self.available_operators
['y', 'n'].map { |s| s.to_operator } ['y', 'n'].map(&:to_operator)
end end
def self.available_values(*) def self.available_values(*)

@ -20,10 +20,10 @@
class CostQuery::Filter::PermissionFilter < Report::Filter::Base class CostQuery::Filter::PermissionFilter < Report::Filter::Base
dont_display! dont_display!
not_selectable! not_selectable!
db_field "" db_field ''
singleton singleton
initialize_query_with { |query| query.filter self.to_s.demodulize.to_sym } initialize_query_with { |query| query.filter to_s.demodulize.to_sym }
def permission_statement(permission) def permission_statement(permission)
User.current.allowed_to_condition_with_project_id(permission).gsub(/(user|project)s?\.id/, '\1_id') User.current.allowed_to_condition_with_project_id(permission).gsub(/(user|project)s?\.id/, '\1_id')
@ -37,10 +37,10 @@ class CostQuery::Filter::PermissionFilter < Report::Filter::Base
def display_costs def display_costs
"(#{permission_statement :view_hourly_rates} " \ "(#{permission_statement :view_hourly_rates} " \
"AND #{permission_statement :view_cost_rates}) " \ "AND #{permission_statement :view_cost_rates}) " \
"OR " \ 'OR ' \
"(#{permission_statement :view_own_hourly_rate} " \ "(#{permission_statement :view_own_hourly_rate} " \
"AND type = 'TimeEntry' AND user_id = #{User.current.id}) " \ "AND type = 'TimeEntry' AND user_id = #{User.current.id}) " \
"OR " \ 'OR ' \
"(#{permission_statement :view_cost_rates} " \ "(#{permission_statement :view_cost_rates} " \
"AND type = 'CostEntry' AND user_id = #{User.current.id})" "AND type = 'CostEntry' AND user_id = #{User.current.id})"
end end
@ -49,8 +49,8 @@ class CostQuery::Filter::PermissionFilter < Report::Filter::Base
super.tap do |query| super.tap do |query|
query.from.each_subselect do |sub| query.from.each_subselect do |sub|
sub.where permission_for(sub == query.from.first ? 'time' : 'cost') sub.where permission_for(sub == query.from.first ? 'time' : 'cost')
sub.select.delete_if { |f| f.end_with? "display_costs" } sub.select.delete_if { |f| f.end_with? 'display_costs' }
sub.select :display_costs => switch(display_costs => '1', :else => 0) sub.select display_costs: switch(display_costs => '1', else: 0)
end end
end end
end end

@ -26,6 +26,6 @@ class CostQuery::Filter::PriorityId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
IssuePriority.find(:all, :order => 'position DESC').map { |i| [i.name, i.id] } IssuePriority.find(:all, order: 'position DESC').map { |i| [i.name, i.id] }
end end
end end

@ -18,14 +18,14 @@
#++ #++
class CostQuery::Filter::ProjectId < Report::Filter::Base class CostQuery::Filter::ProjectId < Report::Filter::Base
db_field "entries.project_id" db_field 'entries.project_id'
def self.label def self.label
Project.model_name.human Project.model_name.human
end end
def self.available_operators def self.available_operators
["=", "!", "=_child_projects", "!_child_projects"].map { |s| s.to_operator } ['=', '!', '=_child_projects', '!_child_projects'].map(&:to_operator)
end end
## ##
@ -37,10 +37,10 @@ class CostQuery::Filter::ProjectId < Report::Filter::Base
map = [] map = []
ancestors = [] ancestors = []
Project.visible.sort_by(&:lft).each do |project| Project.visible.sort_by(&:lft).each do |project|
while (ancestors.any? && !project.is_descendant_of?(ancestors.last)) while ancestors.any? && !project.is_descendant_of?(ancestors.last)
ancestors.pop ancestors.pop
end end
map << [project.name, project.id, {:level => ancestors.size}] map << [project.name, project.id, { level: ancestors.size }]
ancestors << project ancestors << project
end end
map map

@ -17,7 +17,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#++ #++
#we have to require this here because the operators would not be defined otherwise # we have to require this here because the operators would not be defined otherwise
require_dependency 'cost_query/operator' require_dependency 'cost_query/operator'
class CostQuery::Filter::StatusId < Report::Filter::Base class CostQuery::Filter::StatusId < Report::Filter::Base
available_operators 'c', 'o' available_operators 'c', 'o'
@ -29,6 +29,6 @@ class CostQuery::Filter::StatusId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
Status.find(:all, :order => 'name').map { |i| [i.name, i.id] } Status.find(:all, order: 'name').map { |i| [i.name, i.id] }
end end
end end

@ -25,6 +25,6 @@ class CostQuery::Filter::Tmonth < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
1.upto(12).map {|i| [ ::I18n.t('date.month_names')[i], i ]} 1.upto(12).map { |i| [::I18n.t('date.month_names')[i], i] }
end end
end end

@ -25,6 +25,6 @@ class CostQuery::Filter::Tweek < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
1.upto(53).map {|i| [ i.to_s, i ]} 1.upto(53).map { |i| [i.to_s, i] }
end end
end end

@ -25,6 +25,6 @@ class CostQuery::Filter::Tyear < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
1970.upto(Date.today.year).map {|i| [ i.to_s, i ]}.reverse 1970.upto(Date.today.year).map { |i| [i.to_s, i] }.reverse
end end
end end

@ -26,6 +26,6 @@ class CostQuery::Filter::TypeId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
Type.find(:all, :order => 'name').map { |i| [i.name, i.id] } Type.find(:all, order: 'name').map { |i| [i.name, i.id] }
end end
end end

@ -18,7 +18,7 @@
#++ #++
class CostQuery::Filter::UpdatedOn < Report::Filter::Base class CostQuery::Filter::UpdatedOn < Report::Filter::Base
db_field "entries.updated_on" db_field 'entries.updated_on'
use :time_operators use :time_operators
def self.label def self.label

@ -23,9 +23,9 @@ class CostQuery::Filter::UserId < Report::Filter::Base
end end
def self.available_values(*) def self.available_values(*)
users = Project.visible.collect {|p| p.users}.flatten.uniq.sort users = Project.visible.collect(&:users).flatten.uniq.sort
values = users.map { |u| [u.name, u.id] } values = users.map { |u| [u.name, u.id] }
values.delete_if { |u| (u.first.include? "OpenProject Admin") || (u.first.include? "Anonymous")} values.delete_if { |u| (u.first.include? 'OpenProject Admin') || (u.first.include? 'Anonymous') }
values.sort! values.sort!
values.unshift ["<< #{::I18n.t(:label_me)} >>", User.current.id.to_s] if User.current.logged? values.unshift ["<< #{::I18n.t(:label_me)} >>", User.current.id.to_s] if User.current.logged?
values values

@ -18,13 +18,12 @@
#++ #++
class CostQuery::Filter::WorkPackageId < Report::Filter::Base class CostQuery::Filter::WorkPackageId < Report::Filter::Base
def self.label def self.label
WorkPackage.model_name.human WorkPackage.model_name.human
end end
def self.available_values(*) def self.available_values(*)
work_packages = Project.visible.collect { |p| p.work_packages }.flatten.uniq.sort_by { |i| i.id } work_packages = Project.visible.map { |p| p.work_packages }.flatten.uniq.sort_by { |i| i.id }
work_packages.map { |i| [text_for_work_package(i), i.id] } work_packages.map { |i| [text_for_work_package(i), i.id] }
end end
@ -45,12 +44,12 @@ class CostQuery::Filter::WorkPackageId < Report::Filter::Base
def self.text_for_work_package(i) def self.text_for_work_package(i)
i = i.first if i.is_a? Array i = i.first if i.is_a? Array
str = "##{i.id} " str = "##{i.id} "
str << (i.subject.length > 30 ? i.subject.first(26)+'...': i.subject) str << (i.subject.length > 30 ? i.subject.first(26) + '...' : i.subject)
end end
def self.text_for_id(i) def self.text_for_id(i)
text_for_work_package WorkPackage.find(i) text_for_work_package WorkPackage.find(i)
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
"" ''
end end
end end

@ -23,7 +23,7 @@ class CostQuery::GroupBy
def sql_statement def sql_statement
super.tap do |sql| super.tap do |sql|
sql.sum :units => :units, :real_costs => :real_costs, :display_costs => :display_costs sql.sum units: :units, real_costs: :real_costs, display_costs: :display_costs
end end
end end
end end

@ -19,7 +19,7 @@
class CostQuery::Operator < Report::Operator class CostQuery::Operator < Report::Operator
# Operators from Redmine # Operators from Redmine
new "c", :arity => 0, :label => :label_closed do new "c", arity: 0, label: :label_closed do
def modify(query, field, *values) def modify(query, field, *values)
raise "wrong field" if field.to_s.split('.').last != "status_id" raise "wrong field" if field.to_s.split('.').last != "status_id"
query.where "(#{Status.table_name}.is_closed = #{quoted_true})" query.where "(#{Status.table_name}.is_closed = #{quoted_true})"
@ -27,7 +27,7 @@ class CostQuery::Operator < Report::Operator
end end
end end
new "o", :arity => 0, :label => :label_open do new "o", arity: 0, label: :label_open do
def modify(query, field, *values) def modify(query, field, *values)
raise "wrong field" if field.to_s.split('.').last != "status_id" raise "wrong field" if field.to_s.split('.').last != "status_id"
query.where "(#{Status.table_name}.is_closed = #{quoted_false})" query.where "(#{Status.table_name}.is_closed = #{quoted_false})"
@ -35,7 +35,7 @@ class CostQuery::Operator < Report::Operator
end end
end end
new "=_child_projects", :validate => :integers, :label => :label_is_project_with_subprojects do new "=_child_projects", validate: :integers, label: :label_is_project_with_subprojects do
def modify(query, field, *values) def modify(query, field, *values)
p_ids = [] p_ids = []
values.each do |value| values.each do |value|
@ -47,7 +47,7 @@ class CostQuery::Operator < Report::Operator
end end
end end
new "!_child_projects", :validate => :integers, :label => :label_is_not_project_with_subprojects do new "!_child_projects", validate: :integers, label: :label_is_not_project_with_subprojects do
def modify(query, field, *values) def modify(query, field, *values)
p_ids = [] p_ids = []
values.each do |value| values.each do |value|

@ -77,10 +77,10 @@ class CostQuery::SqlStatement < Report::SqlStatement
query.select COMMON_FIELDS query.select COMMON_FIELDS
query.desc = "Subquery for #{table}" query.desc = "Subquery for #{table}"
query.select({ query.select({
:count => 1, :id => [model, :id], :display_costs => 1, count: 1, id: [model, :id], display_costs: 1,
:real_costs => switch("#{table}.overridden_costs IS NULL" => [model, :costs], :else => [model, :overridden_costs]), real_costs: switch("#{table}.overridden_costs IS NULL" => [model, :costs], else: [model, :overridden_costs]),
:week => iso_year_week(:spent_on, model), week: iso_year_week(:spent_on, model),
:singleton_value => 1 }) singleton_value: 1 })
#FIXME: build this subquery from a sql_statement #FIXME: build this subquery from a sql_statement
query.from "(SELECT *, #{typed :text, model.model_name} AS type FROM #{table}) AS #{table}" query.from "(SELECT *, #{typed :text, model.model_name} AS type FROM #{table}) AS #{table}"
send("unify_#{table}", query) send("unify_#{table}", query)
@ -92,8 +92,8 @@ class CostQuery::SqlStatement < Report::SqlStatement
# #
# @param [CostQuery::SqlStatement] query The statement to adjust # @param [CostQuery::SqlStatement] query The statement to adjust
def self.unify_time_entries(query) def self.unify_time_entries(query)
query.select :activity_id, :units => :hours, :cost_type_id => -1 query.select :activity_id, units: :hours, cost_type_id: -1
query.select :cost_type => quoted_label(:caption_labor) query.select cost_type: quoted_label(:caption_labor)
end end
## ##
@ -101,8 +101,8 @@ class CostQuery::SqlStatement < Report::SqlStatement
# #
# @param [CostQuery::SqlStatement] query The statement to adjust # @param [CostQuery::SqlStatement] query The statement to adjust
def self.unify_cost_entries(query) def self.unify_cost_entries(query)
query.select :units, :cost_type_id, :activity_id => -1 query.select :units, :cost_type_id, activity_id: -1
query.select :cost_type => "cost_types.name" query.select cost_type: "cost_types.name"
query.join CostType query.join CostType
end end

@ -119,7 +119,7 @@ Given /^I group (rows|columns) by "([^\"]*)"/ do |target, group|
end end
Given /^I remove "([^\"]*)" from (rows|columns)/ do |group, source| Given /^I remove "([^\"]*)" from (rows|columns)/ do |group, source|
element_name = find_by_id("group_by_#{source}").find("label", :text => "#{group}")[:for] element_name = find_by_id("group_by_#{source}").find("label", text: "#{group}")[:for]
find_by_id("#{element_name}_remove").click find_by_id("#{element_name}_remove").click
end end

@ -17,5 +17,5 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#++ #++
ScenarioDisabler.disable(:feature => "Tracking Time", :scenario => "Adding a time entry") ScenarioDisabler.disable(feature: "Tracking Time", scenario: "Adding a time entry")
ScenarioDisabler.disable(:feature => "Tracking Time", :scenario => "Editing a time entry") ScenarioDisabler.disable(feature: "Tracking Time", scenario: "Editing a time entry")

@ -24,16 +24,16 @@ module OpenProject::Reporting
include OpenProject::Plugins::ActsAsOpEngine include OpenProject::Plugins::ActsAsOpEngine
register 'openproject-reporting', register 'openproject-reporting',
:author_url => 'http://finn.de', author_url: 'http://finn.de',
:requires_openproject => '>= 4.0.0' do requires_openproject: '>= 4.0.0' do
view_actions = [:index, :show, :drill_down, :available_values, :display_report_list] view_actions = [:index, :show, :drill_down, :available_values, :display_report_list]
edit_actions = [:create, :update, :rename, :delete] edit_actions = [:create, :update, :rename, :delete]
#register reporting_module including permissions #register reporting_module including permissions
project_module :reporting_module do project_module :reporting_module do
permission :save_cost_reports, {:cost_reports => edit_actions} permission :save_cost_reports, {cost_reports: edit_actions}
permission :save_private_cost_reports, {:cost_reports => edit_actions} permission :save_private_cost_reports, {cost_reports: edit_actions}
end end
#register additional permissions for viewing time and cost entries through the CostReportsController #register additional permissions for viewing time and cost entries through the CostReportsController
@ -45,23 +45,23 @@ module OpenProject::Reporting
end end
#menu extensions #menu extensions
menu :top_menu, :cost_reports_global, {:controller => 'cost_reports', :action => 'index', :project_id => nil}, menu :top_menu, :cost_reports_global, {controller: 'cost_reports', action: 'index', project_id: nil},
:caption => :cost_reports_title, caption: :cost_reports_title,
:if => Proc.new { if: Proc.new {
( User.current.allowed_to?(:view_time_entries, nil, :global => true) || ( User.current.allowed_to?(:view_time_entries, nil, global: true) ||
User.current.allowed_to?(:view_own_time_entries, nil, :global => true) || User.current.allowed_to?(:view_own_time_entries, nil, global: true) ||
User.current.allowed_to?(:view_cost_entries, nil, :global => true) || User.current.allowed_to?(:view_cost_entries, nil, global: true) ||
User.current.allowed_to?(:view_own_cost_entries, nil, :global => true) User.current.allowed_to?(:view_own_cost_entries, nil, global: true)
) )
} }
menu :project_menu, :cost_reports, menu :project_menu, :cost_reports,
{:controller => 'cost_reports', :action => 'index'}, {controller: 'cost_reports', action: 'index'},
:param => :project_id, param: :project_id,
:after => :cost_objects, after: :cost_objects,
:caption => :cost_reports_title, caption: :cost_reports_title,
:if => Proc.new { |project| project.module_enabled?(:reporting_module) }, if: Proc.new { |project| project.module_enabled?(:reporting_module) },
:html => {:class => 'icon2 icon-stats'} html: {class: 'icon2 icon-stats'}
end end
initializer "reporting.register_hooks" do initializer "reporting.register_hooks" do

@ -18,5 +18,5 @@
#++ #++
class ViewProjectsShowSidebarBottomHook < Redmine::Hook::ViewListener class ViewProjectsShowSidebarBottomHook < Redmine::Hook::ViewListener
render_on :view_projects_show_sidebar_bottom, :partial => 'hooks/view_projects_show_sidebar_bottom_hook' render_on :view_projects_show_sidebar_bottom, partial: 'hooks/view_projects_show_sidebar_bottom_hook'
end end

@ -39,7 +39,7 @@ module OpenProject::Reporting::Patches
# This is for cost reporting # This is for cost reporting
def redirect_to(*args, &block) def redirect_to(*args, &block)
if args.first == :back and args.size == 1 and request.referer =~ /cost_reports/ if args.first == :back and args.size == 1 and request.referer =~ /cost_reports/
super(:controller => '/cost_reports', :action => :index) super(controller: '/cost_reports', action: :index)
else else
super(*args, &block) super(*args, &block)
end end
@ -50,11 +50,11 @@ module OpenProject::Reporting::Patches
if @project.nil? || !@project.module_enabled?(:reporting_module) if @project.nil? || !@project.module_enabled?(:reporting_module)
return index_without_reports_view return index_without_reports_view
end end
filters = {:operators => {}, :values => {}} filters = {operators: {}, values: {}}
if @work_package if @work_package
if @work_package.respond_to?("lft") if @work_package.respond_to?("lft")
work_package_ids = WorkPackage.all(:select => :id, :conditions => ["root_id = ? AND lft >= ? AND rgt <= ?", @work_package.root_id, @work_package.lft, @work_package.rgt]).collect{|i| i.id} work_package_ids = WorkPackage.all(select: :id, conditions: ["root_id = ? AND lft >= ? AND rgt <= ?", @work_package.root_id, @work_package.lft, @work_package.rgt]).collect{|i| i.id}
else else
work_package_ids = [@work_package.id] work_package_ids = [@work_package.id]
end end
@ -68,12 +68,12 @@ module OpenProject::Reporting::Patches
respond_to do |format| respond_to do |format|
format.html { format.html {
session[CostQuery.name.underscore.to_sym] = { :filters => filters, :groups => {:rows => [], :columns => []} } session[CostQuery.name.underscore.to_sym] = { filters: filters, groups: {rows: [], columns: []} }
if @cost_type if @cost_type
redirect_to :controller => "/cost_reports", :action => "index", :project_id => @project, :unit => @cost_type.id redirect_to controller: "/cost_reports", action: "index", project_id: @project, unit: @cost_type.id
else else
redirect_to :controller => "/cost_reports", :action => "index", :project_id => @project redirect_to controller: "/cost_reports", action: "index", project_id: @project
end end
return return
} }
@ -85,8 +85,8 @@ module OpenProject::Reporting::Patches
def find_optional_project_with_own def find_optional_project_with_own
find_optional_project_without_own find_optional_project_without_own
deny_access unless User.current.allowed_to?(:view_cost_entries, @project, :global => true) || deny_access unless User.current.allowed_to?(:view_cost_entries, @project, global: true) ||
User.current.allowed_to?(:view_own_cost_entries, @project, :global => true) User.current.allowed_to?(:view_own_cost_entries, @project, global: true)
end end
end end
end end

@ -39,7 +39,7 @@ module OpenProject::Reporting::Patches
# This is for cost reporting # This is for cost reporting
def redirect_to(*args, &block) def redirect_to(*args, &block)
if args.first == :back and args.size == 1 and request.referer =~ /cost_reports/ if args.first == :back and args.size == 1 and request.referer =~ /cost_reports/
super(:controller => '/cost_reports', :action => :index) super(controller: '/cost_reports', action: :index)
else else
super(*args, &block) super(*args, &block)
end end
@ -50,11 +50,11 @@ module OpenProject::Reporting::Patches
if @project.nil? || !@project.module_enabled?(:reporting_module) if @project.nil? || !@project.module_enabled?(:reporting_module)
return index_without_reports_view return index_without_reports_view
end end
filters = {:operators => {}, :values => {}} filters = {operators: {}, values: {}}
if @issue if @issue
if @issue.respond_to?("lft") if @issue.respond_to?("lft")
work_package_ids = WorkPackage.all(:select => :id, :conditions => ["root_id = ? AND lft >= ? AND rgt <= ?", @issue.root_id, @issue.lft, @issue.rgt]).collect{|i| i.id.to_s} work_package_ids = WorkPackage.all(select: :id, conditions: ["root_id = ? AND lft >= ? AND rgt <= ?", @issue.root_id, @issue.lft, @issue.rgt]).collect{|i| i.id.to_s}
else else
work_package_ids = [@issue.id.to_s] work_package_ids = [@issue.id.to_s]
end end
@ -68,9 +68,9 @@ module OpenProject::Reporting::Patches
respond_to do |format| respond_to do |format|
format.html { format.html {
session[::CostQuery.name.underscore.to_sym] = { :filters => filters, :groups => {:rows => [], :columns => []} } session[::CostQuery.name.underscore.to_sym] = { filters: filters, groups: {rows: [], columns: []} }
redirect_to :controller => "/cost_reports", :action => "index", :project_id => @project, :unit => -1 redirect_to controller: "/cost_reports", action: "index", project_id: @project, unit: -1
} }
format.all { format.all {
index_without_report_view index_without_report_view
@ -85,8 +85,8 @@ module OpenProject::Reporting::Patches
elsif !params[:project_id].blank? elsif !params[:project_id].blank?
@project = Project.find(params[:project_id]) @project = Project.find(params[:project_id])
end end
deny_access unless User.current.allowed_to?(:view_time_entries, @project, :global => true) || deny_access unless User.current.allowed_to?(:view_time_entries, @project, global: true) ||
User.current.allowed_to?(:view_own_time_entries, @project, :global => true) User.current.allowed_to?(:view_own_time_entries, @project, global: true)
end end
end end
end end

@ -23,27 +23,27 @@ class Widget::Table::EntryTable < Widget::Table
detailed_table self detailed_table self
def render def render
content = content_tag :table, { :class => "report detail-report", :id => "sortable-table" } do content = content_tag :table, { class: "report detail-report", id: "sortable-table" } do
concat head concat head
concat foot concat foot
concat body concat body
end end
# FIXME do that js-only, like a man's man # FIXME do that js-only, like a man's man
render_widget Widget::Table::SortableInit, @subject, :to => content, :sort_first_row => true render_widget Widget::Table::SortableInit, @subject, to: content, sort_first_row: true
write content write content
end end
def head def head
content_tag :thead do content_tag :thead do
content_tag :tr do content_tag :tr do
Fields.collect { |field| concat content_tag(:th) { label_for(field) } } Fields.map { |field| concat content_tag(:th) { label_for(field) } }
concat content_tag(:th, :class => 'right') { cost_type.try(:unit_plural) || l(:units) } concat content_tag(:th, class: 'right') { cost_type.try(:unit_plural) || l(:units) }
concat content_tag(:th, :class => 'right') { CostEntry.human_attribute_name(:costs) } concat content_tag(:th, class: 'right') { CostEntry.human_attribute_name(:costs) }
hit = false hit = false
@subject.each_direct_result do |result| @subject.each_direct_result do |result|
next if hit next if hit
if entry_for(result).editable_by? User.current if entry_for(result).editable_by? User.current
concat content_tag(:th, :class => "unsortable") { "&nbsp;".html_safe } concat content_tag(:th, class: "unsortable") { "&nbsp;".html_safe }
hit = true hit = true
end end
end end
@ -55,12 +55,12 @@ class Widget::Table::EntryTable < Widget::Table
content_tag :tfoot do content_tag :tfoot do
content_tag :tr do content_tag :tr do
if show_result(@subject, 0) != show_result(@subject) if show_result(@subject, 0) != show_result(@subject)
concat content_tag(:th, show_result(@subject), :class => "inner right", :colspan => Fields.size + 1) concat content_tag(:th, show_result(@subject), class: "inner right", colspan: Fields.size + 1)
concat content_tag(:th, show_result(@subject, 0), :class => "result right") concat content_tag(:th, show_result(@subject, 0), class: "result right")
else else
concat content_tag(:th, show_result(@subject), :class => "result right", :colspan => Fields.size + 2) concat content_tag(:th, show_result(@subject), class: "result right", colspan: Fields.size + 2)
end end
concat content_tag(:th, "", :class => "unsortable") concat content_tag(:th, "", class: "unsortable")
end end
end end
end end
@ -70,18 +70,18 @@ class Widget::Table::EntryTable < Widget::Table
rows = "".html_safe rows = "".html_safe
@subject.each_direct_result do |result| @subject.each_direct_result do |result|
odd = !odd odd = !odd
rows << (content_tag(:tr, :class => (odd ? "odd" : "even")) do rows << (content_tag(:tr, class: (odd ? "odd" : "even")) do
"".html_safe "".html_safe
Fields.each do |field| Fields.each do |field|
concat content_tag(:td, show_field(field, result.fields[field.to_s]).html_safe, concat content_tag(:td, show_field(field, result.fields[field.to_s]).html_safe,
:"raw-data" => raw_field(field, result.fields[field.to_s]), :"raw-data" => raw_field(field, result.fields[field.to_s]),
:class => "left") class: "left")
end end
concat content_tag :td, show_result(result, result.fields['cost_type_id'].to_i).html_safe, concat content_tag :td, show_result(result, result.fields['cost_type_id'].to_i).html_safe,
:class => "units right", :"raw-data" => result.units class: "units right", :"raw-data" => result.units
concat content_tag :td, (show_result(result, 0)).html_safe, concat content_tag :td, (show_result(result, 0)).html_safe,
:class => "currency right", :"raw-data" => result.real_costs class: "currency right", :"raw-data" => result.real_costs
concat content_tag :td, icons(result), :style => "width: 40px" concat content_tag :td, icons(result), style: "width: 40px"
end) end)
end end
rows rows
@ -93,16 +93,16 @@ class Widget::Table::EntryTable < Widget::Table
with_project(result.fields['project_id']) do with_project(result.fields['project_id']) do
if entry_for(result).editable_by? User.current if entry_for(result).editable_by? User.current
icons = link_to(icon_wrapper('icon-context icon-edit', l(:button_edit)), icons = link_to(icon_wrapper('icon-context icon-edit', l(:button_edit)),
action_for(result, :action => 'edit'), action_for(result, action: 'edit'),
:class => 'no-decoration-on-hover', class: 'no-decoration-on-hover',
:title => l(:button_edit)) title: l(:button_edit))
icons << link_to(icon_wrapper('icon-context icon-delete', l(:button_delete)), icons << link_to(icon_wrapper('icon-context icon-delete', l(:button_delete)),
(action_for(result, :action => 'destroy').reverse_merge(:authenticity_token => form_authenticity_token)), (action_for(result, action: 'destroy').reverse_merge(authenticity_token: form_authenticity_token)),
:title => l(:button_edit), title: l(:button_edit),
:confirm => l(:text_are_you_sure), confirm: l(:text_are_you_sure),
:method => :delete, method: :delete,
:class => 'no-decoration-on-hover', class: 'no-decoration-on-hover',
:title => l(:button_delete)) title: l(:button_delete))
end end
end end
icons icons

@ -27,10 +27,10 @@ class Widget::Settings < Widget::Base
@@settings_to_render.insert -2, :cost_types @@settings_to_render.insert -2, :cost_types
def render_cost_types_settings def render_cost_types_settings
render_widget Widget::Settings::Fieldset, @subject, { :type => "units" } do render_widget Widget::Settings::Fieldset, @subject, { type: "units" } do
render_widget Widget::CostTypes, render_widget Widget::CostTypes,
@cost_types, @cost_types,
:selected_type_id => @selected_type_id selected_type_id: @selected_type_id
end end
end end

@ -21,16 +21,16 @@ class Widget::Table::SimpleTable < Widget::Table
simple_table self simple_table self
def render def render
@list = @subject.collect {|r| r.important_fields }.flatten.uniq @list = @subject.map {|r| r.important_fields }.flatten.uniq
@show_units = @list.include? "cost_type_id" @show_units = @list.include? "cost_type_id"
content = content_tag :table, { :class => "report", :id => "sortable-table" } do content = content_tag :table, { class: "report", id: "sortable-table" } do
concat head concat head
concat foot concat foot
concat body concat body
end end
# FIXME do that js-only, like a man's man # FIXME do that js-only, like a man's man
render_widget Widget::Table::SortableInit, @subject, :to => content render_widget Widget::Table::SortableInit, @subject, to: content
write content.html_safe write content.html_safe
end end
@ -38,10 +38,10 @@ class Widget::Table::SimpleTable < Widget::Table
content_tag :thead do content_tag :thead do
content_tag :tr do content_tag :tr do
@list.each do |field| @list.each do |field|
concat content_tag(:th, :class => "right") { label_for(field) } concat content_tag(:th, class: "right") { label_for(field) }
end end
concat content_tag(:th, :class => "right") { label_for(:units) } if @show_units concat content_tag(:th, class: "right") { label_for(:units) } if @show_units
concat content_tag(:th, :class => "right") { label_for(:label_sum) } concat content_tag(:th, class: "right") { label_for(:label_sum) }
end end
end end
end end
@ -49,8 +49,8 @@ class Widget::Table::SimpleTable < Widget::Table
def foot def foot
content_tag :tfoot do content_tag :tfoot do
content_tag :tr do content_tag :tr do
concat content_tag(:th, '', :class => "result inner", :colspan => @list.size) concat content_tag(:th, '', class: "result inner", colspan: @list.size)
concat content_tag(:th, show_result(@subject), (@show_units ? {:class => "result right", :colspan => "2"} : {:class => "result right"})) concat content_tag(:th, show_result(@subject), (@show_units ? {class: "result right", colspan: "2"} : {class: "result right"}))
end end
end end
end end
@ -58,7 +58,7 @@ class Widget::Table::SimpleTable < Widget::Table
def body def body
content_tag :tbody do content_tag :tbody do
@subject.each do |result| @subject.each do |result|
concat (content_tag :tr, :class => cycle("odd", "even") do concat (content_tag :tr, class: cycle("odd", "even") do
concat (content_tag :td, :'raw-data' => raw_field(*result.fields.first) do concat (content_tag :td, :'raw-data' => raw_field(*result.fields.first) do
show_row result show_row result
end) end)

@ -22,7 +22,7 @@ class Widget::Table::SortableInit < Widget::Base
def render def render
sort_first_row = @options[:sort_first_row] || false sort_first_row = @options[:sort_first_row] || false
write (content_tag :script, :type => "text/javascript" do write (content_tag :script, type: "text/javascript" do
content = %Q{//<![CDATA[ content = %Q{//<![CDATA[
var table_date_header = $$('#sortable-table th').first(); var table_date_header = $$('#sortable-table th').first();
sortables_init(); }.html_safe sortables_init(); }.html_safe

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe CostReportsController, :type => :controller do describe CostReportsController, type: :controller do
include OpenProject::Reporting::PluginSpecHelper include OpenProject::Reporting::PluginSpecHelper
let(:user) { FactoryGirl.build(:user) } let(:user) { FactoryGirl.build(:user) }
@ -34,7 +34,7 @@ describe CostReportsController, :type => :controller do
describe "WHEN providing invalid units describe "WHEN providing invalid units
WHEN having the view_cost_entries permission" do WHEN having the view_cost_entries permission" do
before do before do
get :show, :id => 1, :unit => -1 get :show, id: 1, unit: -1
end end
it "should respond with a 404 error" do it "should respond with a 404 error" do

@ -19,8 +19,8 @@
FactoryGirl.define do FactoryGirl.define do
factory :cost_query do factory :cost_query do
association :user, :factory => :user association :user, factory: :user
association :project, :factory => :project association :project, factory: :project
sequence(:name) { |n| "Cost Query #{n}" } sequence(:name) { |n| "Cost Query #{n}" }
factory :private_cost_query do factory :private_cost_query do
is_public false is_public false

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
let(:project) { FactoryGirl.create(:project) } let(:project) { FactoryGirl.create(:project) }
minimal_query minimal_query
@ -107,14 +107,14 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
@query.filter :project_id @query.filter :project_id
@query.group_by :project_id @query.group_by :project_id
expect(@query.filters.size).to eq(2) expect(@query.filters.size).to eq(2)
expect(@query.filters.collect {|f| f.class.underscore_name}).to include "project_id" expect(@query.filters.map {|f| f.class.underscore_name}).to include "project_id"
end end
it "should return all group_bys" do it "should return all group_bys" do
@query.filter :project_id @query.filter :project_id
@query.group_by :project_id @query.group_by :project_id
expect(@query.group_bys.size).to eq(1) expect(@query.group_bys.size).to eq(1)
expect(@query.group_bys.collect {|g| g.class.underscore_name}).to include "project_id" expect(@query.group_bys.map {|g| g.class.underscore_name}).to include "project_id"
end end
it "should initialize the chain through a block" do it "should initialize the chain through a block" do
@ -123,17 +123,17 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
CostQuery CostQuery
end end
end end
TestFilter.send(:initialize_query_with) {|query| query.filter(:project_id, :value => project.id)} TestFilter.send(:initialize_query_with) {|query| query.filter(:project_id, value: project.id)}
@query.build_new_chain @query.build_new_chain
expect(@query.filters.collect {|f| f.class.underscore_name}).to include "project_id" expect(@query.filters.map {|f| f.class.underscore_name}).to include "project_id"
expect(@query.filters.detect {|f| f.class.underscore_name == "project_id"}.values).to eq(Array(project.id)) expect(@query.filters.detect {|f| f.class.underscore_name == "project_id"}.values).to eq(Array(project.id))
end end
context "store and load" do context "store and load" do
before do before do
@query.filter :project_id, :value => project.id @query.filter :project_id, value: project.id
@query.filter :cost_type_id, :value => CostQuery::Filter::CostTypeId.available_values.first @query.filter :cost_type_id, value: CostQuery::Filter::CostTypeId.available_values.first
@query.filter :category_id, :value => CostQuery::Filter::CategoryId.available_values.first @query.filter :category_id, value: CostQuery::Filter::CategoryId.available_values.first
@query.group_by :activity_id @query.group_by :activity_id
@query.group_by :cost_object_id @query.group_by :cost_object_id
@query.group_by :cost_type_id @query.group_by :cost_type_id
@ -202,7 +202,7 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
describe :inherited_attribute do describe :inherited_attribute do
before do before do
@a = Class.new Report::Chainable @a = Class.new Report::Chainable
@a.inherited_attribute :foo, :default => 42 @a.inherited_attribute :foo, default: 42
@b = Class.new @a @b = Class.new @a
@c = Class.new @a @c = Class.new @a
@d = Class.new @b @d = Class.new @b
@ -227,14 +227,14 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it 'is able to map values' do it 'is able to map values' do
@a.inherited_attribute :bar, :map => proc { |x| x*2 } @a.inherited_attribute :bar, map: proc { |x| x*2 }
@a.bar 21 @a.bar 21
expect(@a.bar).to eq(42) expect(@a.bar).to eq(42)
end end
describe :list do describe :list do
it "merges lists" do it "merges lists" do
@a.inherited_attribute :bar, :list => true @a.inherited_attribute :bar, list: true
@a.bar 1; @b.bar 2; @d.bar 3, 4 @a.bar 1; @b.bar 2; @d.bar 3, 4
expect(@a.bar).to eq([1]) expect(@a.bar).to eq([1])
expect(@b.bar.sort).to eq([1, 2]) expect(@b.bar.sort).to eq([1, 2])
@ -243,7 +243,7 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "is able to map lists" do it "is able to map lists" do
@a.inherited_attribute :bar, :list => true, :map => :to_s @a.inherited_attribute :bar, list: true, map: :to_s
@a.bar 1; @b.bar 1; @d.bar 1 @a.bar 1; @b.bar 1; @d.bar 1
expect(@a.bar).to eq(%w[1]) expect(@a.bar).to eq(%w[1])
expect(@b.bar).to eq(%w[1 1]) expect(@b.bar).to eq(%w[1 1])
@ -252,14 +252,14 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "is able to produce uniq lists" do it "is able to produce uniq lists" do
@a.inherited_attribute :bar, :list => true, :uniq => true @a.inherited_attribute :bar, list: true, uniq: true
@a.bar 1, 1, 2 @a.bar 1, 1, 2
@b.bar 2, 3 @b.bar 2, 3
expect(@b.bar.sort).to eq([1, 2, 3]) expect(@b.bar.sort).to eq([1, 2, 3])
end end
it "keeps old entries" do it "keeps old entries" do
@a.inherited_attribute :bar, :list => true @a.inherited_attribute :bar, list: true
@a.bar 1 @a.bar 1
@a.bar 2 @a.bar 2
expect(@a.bar.sort).to eq([1, 2]) expect(@a.bar.sort).to eq([1, 2])

@ -19,7 +19,7 @@
require File.dirname(__FILE__) + '/../../spec_helper' require File.dirname(__FILE__) + '/../../spec_helper'
describe User, "#destroy", :type => :model do describe User, "#destroy", type: :model do
let(:substitute_user) { DeletedUser.first } let(:substitute_user) { DeletedUser.first }
let(:private_query) { FactoryGirl.create(:private_cost_query) } let(:private_query) { FactoryGirl.create(:private_cost_query) }
let(:public_query) { FactoryGirl.create(:public_cost_query) } let(:public_query) { FactoryGirl.create(:public_cost_query) }
@ -49,7 +49,7 @@ describe User, "#destroy", :type => :model do
describe "WHEN the filter has the deleted user as it's value" do describe "WHEN the filter has the deleted user as it's value" do
before do before do
public_query.filter(filter_symbol, :values => [user.id.to_s], :operator => "=") public_query.filter(filter_symbol, values: [user.id.to_s], operator: "=")
public_query.save! public_query.save!
user.destroy user.destroy
@ -60,7 +60,7 @@ describe User, "#destroy", :type => :model do
describe "WHEN the filter has another user as it's value" do describe "WHEN the filter has another user as it's value" do
before do before do
public_query.filter(filter_symbol, :values => [user2.id.to_s], :operator => "=") public_query.filter(filter_symbol, values: [user2.id.to_s], operator: "=")
public_query.save! public_query.save!
user.destroy user.destroy
@ -72,7 +72,7 @@ describe User, "#destroy", :type => :model do
describe "WHEN the filter has the deleted user and another user as it's value" do describe "WHEN the filter has the deleted user and another user as it's value" do
before do before do
public_query.filter(filter_symbol, :values => [user.id.to_s, user2.id.to_s], :operator => "=") public_query.filter(filter_symbol, values: [user.id.to_s, user2.id.to_s], operator: "=")
public_query.save! public_query.save!
user.destroy user.destroy

@ -19,18 +19,18 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
minimal_query minimal_query
let!(:project) { FactoryGirl.create(:project_with_types) } let!(:project) { FactoryGirl.create(:project_with_types) }
let!(:user) { FactoryGirl.create(:user, :member_in_project => project) } let!(:user) { FactoryGirl.create(:user, member_in_project: project) }
def create_work_package_with_entry(entry_type, work_package_params={}, entry_params = {}) def create_work_package_with_entry(entry_type, work_package_params={}, entry_params = {})
work_package_params = {:project => project}.merge!(work_package_params) work_package_params = {project: project}.merge!(work_package_params)
work_package = FactoryGirl.create(:work_package, work_package_params) work_package = FactoryGirl.create(:work_package, work_package_params)
entry_params = {:work_package => work_package, entry_params = {work_package: work_package,
:project => work_package_params[:project], project: work_package_params[:project],
:user => user}.merge!(entry_params) user: user}.merge!(entry_params)
FactoryGirl.create(entry_type, entry_params) FactoryGirl.create(entry_type, entry_params)
work_package work_package
end end
@ -68,43 +68,43 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
describe filter do describe filter do
let!(:non_matching_entry) { FactoryGirl.create(:cost_entry) } let!(:non_matching_entry) { FactoryGirl.create(:cost_entry) }
let!(:object) { send(object_name) } let!(:object) { send(object_name) }
let!(:author) { FactoryGirl.create(:user, :member_in_project => project) } let!(:author) { FactoryGirl.create(:user, member_in_project: project) }
let!(:work_package) { FactoryGirl.create(:work_package, :project => project, let!(:work_package) { FactoryGirl.create(:work_package, project: project,
:author => author) } author: author) }
let!(:cost_type) { FactoryGirl.create(:cost_type) } let!(:cost_type) { FactoryGirl.create(:cost_type) }
let!(:cost_entry) { FactoryGirl.create(:cost_entry, :work_package => work_package, let!(:cost_entry) { FactoryGirl.create(:cost_entry, work_package: work_package,
:user => user, user: user,
:project => project, project: project,
:cost_type => cost_type) } cost_type: cost_type) }
let!(:activity) { FactoryGirl.create(:time_entry_activity) } let!(:activity) { FactoryGirl.create(:time_entry_activity) }
let!(:time_entry) { FactoryGirl.create(:time_entry, :work_package => work_package, let!(:time_entry) { FactoryGirl.create(:time_entry, work_package: work_package,
:user => user, user: user,
:project => project, project: project,
:activity => activity) } activity: activity) }
it "should only return entries from the given #{filter.to_s}" do it "should only return entries from the given #{filter.to_s}" do
@query.filter field, :value => object.id @query.filter field, value: object.id
@query.result.each do |result| @query.result.each do |result|
expect(result[field].to_s).to eq(object.id.to_s) expect(result[field].to_s).to eq(object.id.to_s)
end end
end end
it "should allow chaining the same filter" do it "should allow chaining the same filter" do
@query.filter field, :value => object.id @query.filter field, value: object.id
@query.filter field, :value => object.id @query.filter field, value: object.id
@query.result.each do |result| @query.result.each do |result|
expect(result[field].to_s).to eq(object.id.to_s) expect(result[field].to_s).to eq(object.id.to_s)
end end
end end
it "should return no results for excluding filters" do it "should return no results for excluding filters" do
@query.filter field, :value => object.id @query.filter field, value: object.id
@query.filter field, :value => object.id + 1 @query.filter field, value: object.id + 1
expect(@query.result.count).to eq(0) expect(@query.result.count).to eq(0)
end end
it "should compute the correct number of results" do it "should compute the correct number of results" do
@query.filter field, :value => object.id @query.filter field, value: object.id
expect(@query.result.count).to eq(expected_count) expect(@query.result.count).to eq(expected_count)
end end
end end
@ -114,22 +114,22 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
describe CostQuery::Filter::AuthorId do describe CostQuery::Filter::AuthorId do
let!(:non_matching_entry) { FactoryGirl.create(:cost_entry) } let!(:non_matching_entry) { FactoryGirl.create(:cost_entry) }
let!(:author) { FactoryGirl.create(:user, :member_in_project => project) } let!(:author) { FactoryGirl.create(:user, member_in_project: project) }
let!(:work_package) { FactoryGirl.create(:work_package, :project => project, let!(:work_package) { FactoryGirl.create(:work_package, project: project,
:author => author) } author: author) }
let!(:cost_type) { FactoryGirl.create(:cost_type) } let!(:cost_type) { FactoryGirl.create(:cost_type) }
let!(:cost_entry) { FactoryGirl.create(:cost_entry, :work_package => work_package, let!(:cost_entry) { FactoryGirl.create(:cost_entry, work_package: work_package,
:user => user, user: user,
:project => project, project: project,
:cost_type => cost_type) } cost_type: cost_type) }
let!(:activity) { FactoryGirl.create(:time_entry_activity) } let!(:activity) { FactoryGirl.create(:time_entry_activity) }
let!(:time_entry) { FactoryGirl.create(:time_entry, :work_package => work_package, let!(:time_entry) { FactoryGirl.create(:time_entry, work_package: work_package,
:user => user, user: user,
:project => project, project: project,
:activity => activity) } activity: activity) }
it "should only return entries from the given CostQuery::Filter::AuthorId" do it "should only return entries from the given CostQuery::Filter::AuthorId" do
@query.filter 'author_id', :value => author.id @query.filter 'author_id', value: author.id
@query.result.each do |result| @query.result.each do |result|
work_package_id = result["work_package_id"] work_package_id = result["work_package_id"]
expect(WorkPackage.find(work_package_id).author.id).to eq(author.id) expect(WorkPackage.find(work_package_id).author.id).to eq(author.id)
@ -137,8 +137,8 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "should allow chaining the same filter" do it "should allow chaining the same filter" do
@query.filter 'author_id', :value => author.id @query.filter 'author_id', value: author.id
@query.filter 'author_id', :value => author.id @query.filter 'author_id', value: author.id
@query.result.each do |result| @query.result.each do |result|
work_package_id = result["work_package_id"] work_package_id = result["work_package_id"]
expect(WorkPackage.find(work_package_id).author.id).to eq(author.id) expect(WorkPackage.find(work_package_id).author.id).to eq(author.id)
@ -146,30 +146,30 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "should return no results for excluding filters" do it "should return no results for excluding filters" do
@query.filter 'author_id', :value => author.id @query.filter 'author_id', value: author.id
@query.filter 'author_id', :value => author.id + 1 @query.filter 'author_id', value: author.id + 1
expect(@query.result.count).to eq(0) expect(@query.result.count).to eq(0)
end end
it "should compute the correct number of results" do it "should compute the correct number of results" do
@query.filter 'author_id', :value => author.id @query.filter 'author_id', value: author.id
expect(@query.result.count).to eq(2) expect(@query.result.count).to eq(2)
end end
end end
it "filters spent_on" do it "filters spent_on" do
@query.filter :spent_on, :operator=> 'w' @query.filter :spent_on, operator: 'w'
expect(@query.result.count).to eq(Entry.all.select { |e| e.spent_on.cweek == TimeEntry.all.first.spent_on.cweek }.count) expect(@query.result.count).to eq(Entry.all.select { |e| e.spent_on.cweek == TimeEntry.all.first.spent_on.cweek }.count)
end end
it "filters created_on" do it "filters created_on" do
@query.filter :created_on, :operator => 't' @query.filter :created_on, operator: 't'
# we assume that some of our fixtures set created_on to Time.now # we assume that some of our fixtures set created_on to Time.now
expect(@query.result.count).to eq(Entry.all.select { |e| e.created_on.to_date == Date.today }.count) expect(@query.result.count).to eq(Entry.all.select { |e| e.created_on.to_date == Date.today }.count)
end end
it "filters updated_on" do it "filters updated_on" do
@query.filter :updated_on, :value => Date.today.years_ago(20), :operator => '>d' @query.filter :updated_on, value: Date.today.years_ago(20), operator: '>d'
# we assume that our were updated in the last 20 years # we assume that our were updated in the last 20 years
expect(@query.result.count).to eq(Entry.all.select { |e| e.updated_on.to_date > Date.today.years_ago(20) }.count) expect(@query.result.count).to eq(Entry.all.select { |e| e.updated_on.to_date > Date.today.years_ago(20) }.count)
end end
@ -178,10 +178,10 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
old_user = User.current old_user = User.current
# create non-matching entry # create non-matching entry
anonymous = FactoryGirl.create(:anonymous) anonymous = FactoryGirl.create(:anonymous)
create_work_package_with_time_entry({}, {:user => anonymous}) create_work_package_with_time_entry({}, {user: anonymous})
# create matching entry # create matching entry
create_work_package_with_time_entry() create_work_package_with_time_entry()
@query.filter :user_id, :value => user.id, :operator => '=' @query.filter :user_id, value: user.id, operator: '='
expect(@query.result.count).to eq(1) expect(@query.result.count).to eq(1)
end end
@ -199,80 +199,80 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "filters overridden_costs" do it "filters overridden_costs" do
@query.filter :overridden_costs, :operator => 'y' @query.filter :overridden_costs, operator: 'y'
expect(@query.result.count).to eq(Entry.all.select { |e| not e.overridden_costs.nil? }.count) expect(@query.result.count).to eq(Entry.all.select { |e| not e.overridden_costs.nil? }.count)
end end
it "filters status" do it "filters status" do
matching_status = FactoryGirl.create(:status, :is_closed => true) matching_status = FactoryGirl.create(:status, is_closed: true)
create_work_packages_and_time_entries(3, :status => matching_status) create_work_packages_and_time_entries(3, status: matching_status)
@query.filter :status_id, :operator => 'c' @query.filter :status_id, operator: 'c'
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters types" do it "filters types" do
matching_type = project.types.first matching_type = project.types.first
create_work_packages_and_time_entries(3, :type => matching_type) create_work_packages_and_time_entries(3, type: matching_type)
@query.filter :type_id, :operator => '=', :value => matching_type.id @query.filter :type_id, operator: '=', value: matching_type.id
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters work_package authors" do it "filters work_package authors" do
matching_author = create_matching_object_with_time_entries(:user, :author, 3) matching_author = create_matching_object_with_time_entries(:user, :author, 3)
@query.filter :author_id, :operator => '=', :value => matching_author.id @query.filter :author_id, operator: '=', value: matching_author.id
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters priority" do it "filters priority" do
matching_priority = create_matching_object_with_time_entries(:priority, :priority, 3) matching_priority = create_matching_object_with_time_entries(:priority, :priority, 3)
@query.filter :priority_id, :operator => '=', :value => matching_priority.id @query.filter :priority_id, operator: '=', value: matching_priority.id
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters assigned to" do it "filters assigned to" do
matching_user = create_matching_object_with_time_entries(:user, :assigned_to, 3) matching_user = create_matching_object_with_time_entries(:user, :assigned_to, 3)
@query.filter :assigned_to_id, :operator => '=', :value => matching_user.id @query.filter :assigned_to_id, operator: '=', value: matching_user.id
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters category" do it "filters category" do
category = create_matching_object_with_time_entries(:category, :category, 3) category = create_matching_object_with_time_entries(:category, :category, 3)
@query.filter :category_id, :operator => '=', :value => category.id @query.filter :category_id, operator: '=', value: category.id
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters target version" do it "filters target version" do
matching_version = FactoryGirl.create(:version, :project => project) matching_version = FactoryGirl.create(:version, project: project)
create_work_packages_and_time_entries(3, :fixed_version => matching_version) create_work_packages_and_time_entries(3, fixed_version: matching_version)
@query.filter :fixed_version_id, :operator => '=', :value => matching_version.id @query.filter :fixed_version_id, operator: '=', value: matching_version.id
expect(@query.result.count).to eq(3) expect(@query.result.count).to eq(3)
end end
it "filters subject" do it "filters subject" do
matching_work_package = create_work_package_with_time_entry(:subject => 'matching subject') matching_work_package = create_work_package_with_time_entry(subject: 'matching subject')
@query.filter :subject, :operator => '=', :value => 'matching subject' @query.filter :subject, operator: '=', value: 'matching subject'
expect(@query.result.count).to eq(1) expect(@query.result.count).to eq(1)
end end
it "filters start" do it "filters start" do
start_date = Date.new(2013, 1, 1) start_date = Date.new(2013, 1, 1)
matching_work_package = create_work_package_with_time_entry(:start_date => start_date) matching_work_package = create_work_package_with_time_entry(start_date: start_date)
@query.filter :start_date, :operator => '=d', :value => start_date @query.filter :start_date, operator: '=d', value: start_date
expect(@query.result.count).to eq(1) expect(@query.result.count).to eq(1)
#Entry.all.select { |e| e.work_package.start_date == WorkPackage.all(:order => "id ASC").first.start_date }.count #Entry.all.select { |e| e.work_package.start_date == WorkPackage.all(:order => "id ASC").first.start_date }.count
end end
it "filters due date" do it "filters due date" do
due_date = Date.new(2013, 1, 1) due_date = Date.new(2013, 1, 1)
matching_work_package = create_work_package_with_time_entry(:due_date => due_date) matching_work_package = create_work_package_with_time_entry(due_date: due_date)
@query.filter :due_date, :operator => '=d', :value => due_date @query.filter :due_date, operator: '=d', value: due_date
expect(@query.result.count).to eq(1) expect(@query.result.count).to eq(1)
#Entry.all.select { |e| e.work_package.due_date == WorkPackage.all(:order => "id ASC").first.due_date }.count #Entry.all.select { |e| e.work_package.due_date == WorkPackage.all(:order => "id ASC").first.due_date }.count
end end
it "raises an error if operator is not supported" do it "raises an error if operator is not supported" do
expect { @query.filter :spent_on, :operator => 'c' }.to raise_error(ArgumentError) expect { @query.filter :spent_on, operator: 'c' }.to raise_error(ArgumentError)
end end
end end
@ -318,7 +318,7 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
describe CostQuery::Filter::CustomFieldEntries do describe CostQuery::Filter::CustomFieldEntries do
let!(:custom_field) do let!(:custom_field) do
cf = FactoryGirl.create(:work_package_custom_field, cf = FactoryGirl.create(:work_package_custom_field,
:name => 'My custom field') name: 'My custom field')
clear_cache clear_cache
cf cf
end end
@ -361,9 +361,9 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "should provide the correct available values" do it "should provide the correct available values" do
FactoryGirl.create(:work_package_custom_field, :name => 'Database', FactoryGirl.create(:work_package_custom_field, name: 'Database',
:field_format => "list", field_format: "list",
:possible_values => ['value']) possible_values: ['value'])
clear_cache clear_cache
ao = class_name_for('Database').constantize.available_operators.map(&:name) ao = class_name_for('Database').constantize.available_operators.map(&:name)
CostQuery::Operator.null_operators.each do |o| CostQuery::Operator.null_operators.each do |o|
@ -372,15 +372,15 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "should update the available values on change" do it "should update the available values on change" do
FactoryGirl.create(:work_package_custom_field, :name => 'Database', FactoryGirl.create(:work_package_custom_field, name: 'Database',
:field_format => "list", field_format: "list",
:possible_values => ['value']) possible_values: ['value'])
update_work_package_custom_field("Database", :field_format => "string") update_work_package_custom_field("Database", field_format: "string")
ao = class_name_for('Database').constantize.available_operators.map(&:name) ao = class_name_for('Database').constantize.available_operators.map(&:name)
CostQuery::Operator.string_operators.each do |o| CostQuery::Operator.string_operators.each do |o|
expect(ao).to include o.name expect(ao).to include o.name
end end
update_work_package_custom_field("Database", :field_format => "int") update_work_package_custom_field("Database", field_format: "int")
ao = class_name_for('Database').constantize.available_operators.map(&:name) ao = class_name_for('Database').constantize.available_operators.map(&:name)
CostQuery::Operator.integer_operators.each do |o| CostQuery::Operator.integer_operators.each do |o|
expect(ao).to include o.name expect(ao).to include o.name
@ -401,33 +401,33 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
def create_searchable_fields_and_values def create_searchable_fields_and_values
searchable_field = FactoryGirl.create(:work_package_custom_field, searchable_field = FactoryGirl.create(:work_package_custom_field,
:field_format => "text", field_format: "text",
:name => "Searchable Field") name: "Searchable Field")
2.times do 2.times do
work_package = create_work_package_with_entry(:cost_entry) work_package = create_work_package_with_entry(:cost_entry)
FactoryGirl.create(:work_package_custom_value, FactoryGirl.create(:work_package_custom_value,
:custom_field => searchable_field, custom_field: searchable_field,
:customized => work_package, customized: work_package,
:value => "125") value: "125")
end end
work_package = create_work_package_with_entry(:cost_entry) work_package = create_work_package_with_entry(:cost_entry)
FactoryGirl.create(:custom_value, FactoryGirl.create(:custom_value,
:custom_field => searchable_field, custom_field: searchable_field,
:value => "non-matching value") value: "non-matching value")
clear_cache clear_cache
end end
it "is usable as filter" do it "is usable as filter" do
create_searchable_fields_and_values create_searchable_fields_and_values
id = WorkPackageCustomField.find_by_name("Searchable Field").id id = WorkPackageCustomField.find_by_name("Searchable Field").id
@query.filter "custom_field_#{id}".to_sym, :operator => '=', :value => "125" @query.filter "custom_field_#{id}".to_sym, operator: '=', value: "125"
expect(@query.result.count).to eq(2) expect(@query.result.count).to eq(2)
end end
it "is usable as filter #2" do it "is usable as filter #2" do
create_searchable_fields_and_values create_searchable_fields_and_values
id = WorkPackageCustomField.find_by_name("Searchable Field").id id = WorkPackageCustomField.find_by_name("Searchable Field").id
@query.filter "custom_field_#{id}".to_sym, :operator => '=', :value => "finnlabs" @query.filter "custom_field_#{id}".to_sym, operator: '=', value: "finnlabs"
expect(@query.result.count).to eq(0) expect(@query.result.count).to eq(0)
end end
end end

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
let!(:type) { FactoryGirl.create(:type) } let!(:type) { FactoryGirl.create(:type) }
let!(:project1){ FactoryGirl.create(:project_with_types, types: [type]) } let!(:project1){ FactoryGirl.create(:project_with_types, types: [type]) }
let!(:work_package1) { FactoryGirl.create(:work_package, project: project1, type: type)} let!(:work_package1) { FactoryGirl.create(:work_package, project: project1, type: type)}
@ -228,17 +228,17 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
def create_work_package_custom_field(name) def create_work_package_custom_field(name)
WorkPackageCustomField.create(:name => name, WorkPackageCustomField.create(name: name,
:min_length => 1, min_length: 1,
:regexp => "", regexp: "",
:is_for_all => true, is_for_all: true,
:max_length => 100, max_length: 100,
:possible_values => "", possible_values: "",
:is_required => false, is_required: false,
:field_format => "string", field_format: "string",
:searchable => true, searchable: true,
:default_value => "Default string", default_value: "Default string",
:editable => true) editable: true)
check_cache check_cache
end end

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
minimal_query minimal_query
let!(:project1){ FactoryGirl.create(:project_with_types) } let!(:project1){ FactoryGirl.create(:project_with_types) }
@ -39,7 +39,7 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
describe "the reporting system" do describe "the reporting system" do
it "should compute group_by and a filter" do it "should compute group_by and a filter" do
@query.group_by :project_id @query.group_by :project_id
@query.filter :status_id, :operator => 'o' @query.filter :status_id, operator: 'o'
sql_result = @query.result sql_result = @query.result
expect(sql_result.size).to eq(2) expect(sql_result.size).to eq(2)
@ -54,9 +54,9 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "should apply two filter and a group_by correctly" do it "should apply two filter and a group_by correctly" do
@query.filter :project_id, :operator => '=', :value => [project1.id] @query.filter :project_id, operator: '=', value: [project1.id]
@query.group_by :user_id @query.group_by :user_id
@query.filter :overridden_costs, :operator => 'n' @query.filter :overridden_costs, operator: 'n'
sql_result = @query.result sql_result = @query.result
expect(sql_result.size).to eq(2) expect(sql_result.size).to eq(2)
@ -71,8 +71,8 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
end end
it "should apply two different filters on the same field" do it "should apply two different filters on the same field" do
@query.filter :project_id, :operator => '=', :value => [project1.id, project2.id] @query.filter :project_id, operator: '=', value: [project1.id, project2.id]
@query.filter :project_id, :operator => '!', :value => [project2.id] @query.filter :project_id, operator: '!', value: [project2.id]
sql_result = @query.result sql_result = @query.result
expect(sql_result.count).to eq(2) expect(sql_result.count).to eq(2)

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
minimal_query minimal_query
let!(:project1) { FactoryGirl.create(:project, name: "project1", created_on: 5.minutes.ago) } let!(:project1) { FactoryGirl.create(:project, name: "project1", created_on: 5.minutes.ago) }
@ -115,95 +115,95 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
#somehow this test doesn't work on sundays #somehow this test doesn't work on sundays
n = query('projects', 'created_on', 'w').size n = query('projects', 'created_on', 'w').size
day_in_this_week = Time.now.at_beginning_of_week + 1.day day_in_this_week = Time.now.at_beginning_of_week + 1.day
Project.mock! :created_on => day_in_this_week Project.mock! created_on: day_in_this_week
expect(query('projects', 'created_on', 'w').size).to eq(n + 1) expect(query('projects', 'created_on', 'w').size).to eq(n + 1)
Project.mock! :created_on => day_in_this_week + 7.days Project.mock! created_on: day_in_this_week + 7.days
Project.mock! :created_on => day_in_this_week - 7.days Project.mock! created_on: day_in_this_week - 7.days
expect(query('projects', 'created_on', 'w').size).to eq(n + 1) expect(query('projects', 'created_on', 'w').size).to eq(n + 1)
end end
it "does t (today)" do it "does t (today)" do
s = query('projects', 'created_on', 't').size s = query('projects', 'created_on', 't').size
Project.mock! :created_on => Date.yesterday Project.mock! created_on: Date.yesterday
expect(query('projects', 'created_on', 't').size).to eq(s) expect(query('projects', 'created_on', 't').size).to eq(s)
Project.mock! :created_on => Time.now Project.mock! created_on: Time.now
expect(query('projects', 'created_on', 't').size).to eq(s + 1) expect(query('projects', 'created_on', 't').size).to eq(s + 1)
end end
it "does <t+ (before the day which is n days in the future)" do it "does <t+ (before the day which is n days in the future)" do
n = query('projects', 'created_on', '<t+', 2).size n = query('projects', 'created_on', '<t+', 2).size
Project.mock! :created_on => Date.tomorrow + 1 Project.mock! created_on: Date.tomorrow + 1
expect(query('projects', 'created_on', '<t+', 2).size).to eq(n + 1) expect(query('projects', 'created_on', '<t+', 2).size).to eq(n + 1)
Project.mock! :created_on => Date.tomorrow + 2 Project.mock! created_on: Date.tomorrow + 2
expect(query('projects', 'created_on', '<t+', 2).size).to eq(n + 1) expect(query('projects', 'created_on', '<t+', 2).size).to eq(n + 1)
end end
it "does t+ (n days in the future)" do it "does t+ (n days in the future)" do
n = query('projects', 'created_on', 't+', 1).size n = query('projects', 'created_on', 't+', 1).size
Project.mock! :created_on => Date.tomorrow Project.mock! created_on: Date.tomorrow
expect(query('projects', 'created_on', 't+', 1).size).to eq(n + 1) expect(query('projects', 'created_on', 't+', 1).size).to eq(n + 1)
Project.mock! :created_on => Date.tomorrow + 2 Project.mock! created_on: Date.tomorrow + 2
expect(query('projects', 'created_on', 't+', 1).size).to eq(n + 1) expect(query('projects', 'created_on', 't+', 1).size).to eq(n + 1)
end end
it "does >t+ (after the day which is n days in the furure)" do it "does >t+ (after the day which is n days in the furure)" do
n = query('projects', 'created_on', '>t+', 1).size n = query('projects', 'created_on', '>t+', 1).size
Project.mock! :created_on => Time.now Project.mock! created_on: Time.now
expect(query('projects', 'created_on', '>t+', 1).size).to eq(n) expect(query('projects', 'created_on', '>t+', 1).size).to eq(n)
Project.mock! :created_on => Date.tomorrow + 1 Project.mock! created_on: Date.tomorrow + 1
expect(query('projects', 'created_on', '>t+', 1).size).to eq(n + 1) expect(query('projects', 'created_on', '>t+', 1).size).to eq(n + 1)
end end
it "does >t- (after the day which is n days ago)" do it "does >t- (after the day which is n days ago)" do
n = query('projects', 'created_on', '>t-', 1).size n = query('projects', 'created_on', '>t-', 1).size
Project.mock! :created_on => Date.today Project.mock! created_on: Date.today
expect(query('projects', 'created_on', '>t-', 1).size).to eq(n + 1) expect(query('projects', 'created_on', '>t-', 1).size).to eq(n + 1)
Project.mock! :created_on => Date.yesterday - 1 Project.mock! created_on: Date.yesterday - 1
expect(query('projects', 'created_on', '>t-', 1).size).to eq(n + 1) expect(query('projects', 'created_on', '>t-', 1).size).to eq(n + 1)
end end
it "does t- (n days ago)" do it "does t- (n days ago)" do
n = query('projects', 'created_on', 't-', 1).size n = query('projects', 'created_on', 't-', 1).size
Project.mock! :created_on => Date.yesterday Project.mock! created_on: Date.yesterday
expect(query('projects', 'created_on', 't-', 1).size).to eq(n + 1) expect(query('projects', 'created_on', 't-', 1).size).to eq(n + 1)
Project.mock! :created_on => Date.yesterday - 2 Project.mock! created_on: Date.yesterday - 2
expect(query('projects', 'created_on', 't-', 1).size).to eq(n + 1) expect(query('projects', 'created_on', 't-', 1).size).to eq(n + 1)
end end
it "does <t- (before the day which is n days ago)" do it "does <t- (before the day which is n days ago)" do
n = query('projects', 'created_on', '<t-', 1).size n = query('projects', 'created_on', '<t-', 1).size
Project.mock! :created_on => Date.today Project.mock! created_on: Date.today
expect(query('projects', 'created_on', '<t-', 1).size).to eq(n) expect(query('projects', 'created_on', '<t-', 1).size).to eq(n)
Project.mock! :created_on => Date.yesterday - 1 Project.mock! created_on: Date.yesterday - 1
expect(query('projects', 'created_on', '<t-', 1).size).to eq(n + 1) expect(query('projects', 'created_on', '<t-', 1).size).to eq(n + 1)
end end
#Our own operators #Our own operators
it "does =_child_projects" do it "does =_child_projects" do
expect(query('projects', 'id', '=_child_projects', project1.id).size).to eq(1) expect(query('projects', 'id', '=_child_projects', project1.id).size).to eq(1)
p_c1 = create_project :parent => project1 p_c1 = create_project parent: project1
expect(query('projects', 'id', '=_child_projects', project1.id).size).to eq(2) expect(query('projects', 'id', '=_child_projects', project1.id).size).to eq(2)
create_project :parent => p_c1 create_project parent: p_c1
expect(query('projects', 'id', '=_child_projects', project1.id).size).to eq(3) expect(query('projects', 'id', '=_child_projects', project1.id).size).to eq(3)
end end
it "does =_child_projects on multiple projects" do it "does =_child_projects on multiple projects" do
expect(query('projects', 'id', '=_child_projects', project1.id, project2.id).size).to eq(2) expect(query('projects', 'id', '=_child_projects', project1.id, project2.id).size).to eq(2)
p1_c1 = create_project :parent => project1 p1_c1 = create_project parent: project1
p2_c1 = create_project :parent => project2 p2_c1 = create_project parent: project2
expect(query('projects', 'id', '=_child_projects', project1.id, project2.id).size).to eq(4) expect(query('projects', 'id', '=_child_projects', project1.id, project2.id).size).to eq(4)
p1_c1_c1 = create_project :parent => p1_c1 p1_c1_c1 = create_project parent: p1_c1
create_project :parent => p1_c1_c1 create_project parent: p1_c1_c1
create_project :parent => p2_c1 create_project parent: p2_c1
expect(query('projects', 'id', '=_child_projects', project1.id, project2.id).size).to eq(7) expect(query('projects', 'id', '=_child_projects', project1.id, project2.id).size).to eq(7)
end end
it "does !_child_projects" do it "does !_child_projects" do
expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(1) expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(1)
p_c1 = create_project :parent => project1 p_c1 = create_project parent: project1
expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(1) expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(1)
create_project :parent => project1 create_project parent: project1
create_project :parent => p_c1 create_project parent: p_c1
expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(1) expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(1)
create_project create_project
expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(2) expect(query('projects', 'id', '!_child_projects', project1.id).size).to eq(2)
@ -211,13 +211,13 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
it "does !_child_projects on multiple projects" do it "does !_child_projects on multiple projects" do
expect(query('projects', 'id', '!_child_projects', project1.id, project2.id).size).to eq(0) expect(query('projects', 'id', '!_child_projects', project1.id, project2.id).size).to eq(0)
p1_c1 = create_project :parent => project1 p1_c1 = create_project parent: project1
p2_c1 = create_project :parent => project2 p2_c1 = create_project parent: project2
create_project create_project
expect(query('projects', 'id', '!_child_projects', project1.id, project2.id).size).to eq(1) expect(query('projects', 'id', '!_child_projects', project1.id, project2.id).size).to eq(1)
p1_c1_c1 = create_project :parent => p1_c1 p1_c1_c1 = create_project parent: p1_c1
create_project :parent => p1_c1_c1 create_project parent: p1_c1_c1
create_project :parent => p2_c1 create_project parent: p2_c1
create_project create_project
expect(query('projects', 'id', '!_child_projects', project1.id, project2.id).size).to eq(2) expect(query('projects', 'id', '!_child_projects', project1.id, project2.id).size).to eq(2)
end end
@ -243,7 +243,7 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
it "does =d" do it "does =d" do
#assuming that there aren't more than one project created at the same time #assuming that there aren't more than one project created at the same time
expect(query('projects', 'created_on', '=d', Project.first(:order => "id ASC").created_on).size).to eq(1) expect(query('projects', 'created_on', '=d', Project.first(order: "id ASC").created_on).size).to eq(1)
end end
it "does <d" do it "does <d" do

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
before do before do
FactoryGirl.create(:admin) FactoryGirl.create(:admin)
project = FactoryGirl.create(:project_with_types) project = FactoryGirl.create(:project_with_types)
@ -32,11 +32,11 @@ describe CostQuery, :type => :model, :reporting_query_helper => true do
describe CostQuery::Result do describe CostQuery::Result do
def direct_results(quantity = 0) def direct_results(quantity = 0)
(1..quantity).collect {|i| CostQuery::Result.new :real_costs=>i.to_f, :count=>1 ,:units=>i.to_f} (1..quantity).map {|i| CostQuery::Result.new real_costs:i.to_f, count:1 ,units:i.to_f}
end end
def wrapped_result(source, quantity=1) def wrapped_result(source, quantity=1)
CostQuery::Result.new((1..quantity).collect { |i| source}) CostQuery::Result.new((1..quantity).map { |i| source})
end end
it "should travel recursively depth-first" do it "should travel recursively depth-first" do

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery::Validation, :type => :model do describe CostQuery::Validation, type: :model do
class CostQuery::SomeBase class CostQuery::SomeBase
include CostQuery::Validation include CostQuery::Validation
end end

@ -19,7 +19,7 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
describe CostQuery, :type => :model, :reporting_query_helper => true do describe CostQuery, type: :model, reporting_query_helper: true do
minimal_query minimal_query
before do before do

@ -20,11 +20,11 @@
module OpenProject::Reporting module OpenProject::Reporting
module PluginSpecHelper module PluginSpecHelper
def is_member(project, user, permissions = []) def is_member(project, user, permissions = [])
role = FactoryGirl.create(:role, :permissions => permissions) role = FactoryGirl.create(:role, permissions: permissions)
FactoryGirl.create(:member, :project => project, FactoryGirl.create(:member, project: project,
:principal => user, principal: user,
:roles => [role]) roles: [role])
end end
end end
end end

@ -20,9 +20,9 @@
class Project class Project
def self.mock!(options = {}) def self.mock!(options = {})
time = Time.now time = Time.now
options = options.reverse_merge({:created_on => time, options = options.reverse_merge({created_on: time,
:identifier => "#{Project.all.size}project#{time.to_i}"[0..19], identifier: "#{Project.all.size}project#{time.to_i}"[0..19],
:name => "Project#{Project.all.size}"}) name: "Project#{Project.all.size}"})
generate! options generate! options
end end
end end

@ -29,5 +29,5 @@ module OpenProject::Reporting
end end
RSpec.configure do |c| RSpec.configure do |c|
c.extend OpenProject::Reporting::QueryHelper, :reporting_query_helper => true c.extend OpenProject::Reporting::QueryHelper, reporting_query_helper: true
end end

Loading…
Cancel
Save