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 »