Feature #41053 » 41053-v2.patch
| app/models/time_entry_query.rb | ||
|---|---|---|
| 91 | 91 | "user_id", | 
| 92 | 92 |       :type => :list_optional, :values => lambda {author_values} | 
| 93 | 93 | ) | 
| 94 | add_available_filter( | |
| 95 | "user.group", | |
| 96 | :type => :list_optional, | |
| 97 |       :name => l("label_attribute_of_user", :name => l(:label_group)), | |
| 98 |       :values => lambda {Group.givable.visible.pluck(:name, :id).map {|name, id| [name, id.to_s]}} | |
| 99 | ) | |
| 100 | add_available_filter( | |
| 101 | "user.role", | |
| 102 | :type => :list_optional, | |
| 103 |       :name => l("label_attribute_of_user", :name => l(:field_role)), | |
| 104 |       :values => lambda {Role.givable.pluck(:name, :id).map {|name, id| [name, id.to_s]}} | |
| 105 | ) | |
| 94 | 106 | add_available_filter( | 
| 95 | 107 | "author_id", | 
| 96 | 108 |       :type => :list_optional, :values => lambda {author_values} | 
| ... | ... | |
| 264 | 276 | sql_for_field(field, operator, value, Project.table_name, "status") | 
| 265 | 277 | end | 
| 266 | 278 | |
| 279 | def sql_for_user_group_field(field, operator, value) | |
| 280 | if operator == '*' # Any group | |
| 281 | groups = Group.givable | |
| 282 | operator = '=' | |
| 283 | elsif operator == '!*' | |
| 284 | groups = Group.givable | |
| 285 | operator = '!' | |
| 286 | else | |
| 287 | groups = Group.where(:id => value).to_a | |
| 288 | end | |
| 289 | groups ||= [] | |
| 290 | ||
| 291 | members_of_groups = groups.inject([]) do |user_ids, group| | |
| 292 | user_ids + group.user_ids | |
| 293 | end.uniq.compact.sort.collect(&:to_s) | |
| 294 | ||
| 295 |     '(' + sql_for_field('user_id', operator, members_of_groups, TimeEntry.table_name, "user_id", false) + ')' | |
| 296 | end | |
| 297 | ||
| 298 | def sql_for_user_role_field(field, operator, value) | |
| 299 | case operator | |
| 300 | when "*", "!*" | |
| 301 | sw = operator == "!*" ? "NOT" : "" | |
| 302 |       nl = operator == "!*" ? "#{TimeEntry.table_name}.user_id IS NULL OR" : "" | |
| 303 | ||
| 304 | subquery = | |
| 305 | "SELECT 1" + | |
| 306 |         " FROM #{Member.table_name}" + | |
| 307 |         " WHERE #{TimeEntry.table_name}.project_id = #{Member.table_name}.project_id AND #{Member.table_name}.user_id = #{TimeEntry.table_name}.user_id" | |
| 308 |       "(#{nl} #{sw} EXISTS (#{subquery}))" | |
| 309 | when "=", "!" | |
| 310 | role_cond = | |
| 311 | if value.any? | |
| 312 |           "#{MemberRole.table_name}.role_id IN (" + value.collect{|val| "'#{self.class.connection.quote_string(val)}'"}.join(",") + ")" | |
| 313 | else | |
| 314 | "1=0" | |
| 315 | end | |
| 316 | sw = operator == "!" ? 'NOT' : '' | |
| 317 |       nl = operator == "!" ? "#{TimeEntry.table_name}.user_id IS NULL OR" : '' | |
| 318 | subquery = | |
| 319 | "SELECT 1" + | |
| 320 |         " FROM #{Member.table_name} inner join #{MemberRole.table_name} on members.id = member_roles.member_id" + | |
| 321 |         " WHERE #{TimeEntry.table_name}.project_id = #{Member.table_name}.project_id AND #{Member.table_name}.user_id = #{TimeEntry.table_name}.user_id AND #{role_cond}" | |
| 322 |       "(#{nl} #{sw} EXISTS (#{subquery}))" | |
| 323 | end | |
| 324 | end | |
| 325 | ||
| 267 | 326 | # Accepts :from/:to params as shortcut filters | 
| 268 | 327 |   def build_from_params(params, defaults={}) | 
| 269 | 328 | super | 
| test/unit/time_entry_query_test.rb | ||
|---|---|---|
| 136 | 136 |     assert !query.available_filters.has_key?('project.status') | 
| 137 | 137 | end | 
| 138 | 138 | |
| 139 | def test_user_group_filter_should_consider_spacified_groups_time_entries | |
| 140 | Group.find(10).users << User.find(2) | |
| 141 | Group.find(11).users << User.find(3) | |
| 142 | ||
| 143 | TimeEntry.delete_all | |
| 144 | t1 = TimeEntry.generate!(:hours => 1.0, :user_id => 2) | |
| 145 | t2 = TimeEntry.generate!(:hours => 2.0, :user_id => 2) | |
| 146 | t3 = TimeEntry.generate!(:hours => 4.0, :user_id => 3) | |
| 147 | ||
| 148 | query = TimeEntryQuery.new(:name => '_') | |
| 149 | result = query.base_scope.to_a | |
| 150 | assert result.include?(t1) | |
| 151 | assert result.include?(t2) | |
| 152 | assert result.include?(t3) | |
| 153 | assert_equal 7.0, query.results_scope.sum(:hours) | |
| 154 | ||
| 155 |     query.add_filter('user.group', '=', ['10']) | |
| 156 | result = query.base_scope.to_a | |
| 157 | assert result.include?(t1) | |
| 158 | assert result.include?(t2) | |
| 159 | assert_not result.include?(t3) | |
| 160 | assert_equal 3.0, query.results_scope.sum(:hours) | |
| 161 | ||
| 162 |     query.add_filter('user.group', '=', ['10', '11']) | |
| 163 | result = query.base_scope.to_a | |
| 164 | assert result.include?(t1) | |
| 165 | assert result.include?(t2) | |
| 166 | assert result.include?(t3) | |
| 167 | assert_equal 7.0, query.results_scope.sum(:hours) | |
| 168 | end | |
| 169 | ||
| 170 | def test_user_role_filter_should_consider_spacified_roles_time_entries | |
| 171 | project = Project.find(1) | |
| 172 | project.members << Member.new(:user_id => 2, :roles => [Role.find(1)]) | |
| 173 | project.members << Member.new(:user_id => 3, :roles => [Role.find(2)]) | |
| 174 | ||
| 175 | TimeEntry.delete_all | |
| 176 | t1 = TimeEntry.generate!(:project => project, :hours => 1.0, :user_id => 2) | |
| 177 | t2 = TimeEntry.generate!(:project => project, :hours => 2.0, :user_id => 2) | |
| 178 | t3 = TimeEntry.generate!(:project => project, :hours => 4.0, :user_id => 3) | |
| 179 | ||
| 180 | query = TimeEntryQuery.new(:project => project, :name => '_') | |
| 181 | result = query.base_scope.to_a | |
| 182 | assert result.include?(t1) | |
| 183 | assert result.include?(t2) | |
| 184 | assert result.include?(t3) | |
| 185 | assert_equal 7.0, query.results_scope.sum(:hours) | |
| 186 | ||
| 187 |     query.add_filter('user.role', '=', ['1']) | |
| 188 | result = query.base_scope.to_a | |
| 189 | assert result.include?(t1) | |
| 190 | assert result.include?(t2) | |
| 191 | assert_not result.include?(t3) | |
| 192 | assert_equal 3.0, query.results_scope.sum(:hours) | |
| 193 | ||
| 194 |     query.add_filter('user.role', '=', ['1', '2']) | |
| 195 | result = query.base_scope.to_a | |
| 196 | assert result.include?(t1) | |
| 197 | assert result.include?(t2) | |
| 198 | assert result.include?(t3) | |
| 199 | assert_equal 7.0, query.results_scope.sum(:hours) | |
| 200 | end | |
| 201 | ||
| 139 | 202 | def test_results_scope_should_be_in_the_same_order_when_paginating | 
| 140 | 203 |     4.times {TimeEntry.generate!} | 
| 141 | 204 | q = TimeEntryQuery.new | 
- « Previous
- 1
- 2
- 3
- Next »