##// END OF EJS Templates
Adds a setting to control done ratio on parent tasks (#5490)....
Jean-Philippe Lang -
r13888:b22105f34a8e
parent child
Show More
@@ -149,6 +149,15 module SettingsHelper
149 options.map {|label, value| [l(label), value.to_s]}
149 options.map {|label, value| [l(label), value.to_s]}
150 end
150 end
151
151
152 def parent_issue_done_ratio_options
153 options = [
154 [:label_parent_task_attributes_derived, 'derived'],
155 [:label_parent_task_attributes_independent, 'independent']
156 ]
157
158 options.map {|label, value| [l(label), value.to_s]}
159 end
160
152 # Returns the options for the date_format setting
161 # Returns the options for the date_format setting
153 def date_format_setting_options(locale)
162 def date_format_setting_options(locale)
154 Setting::DATE_FORMATS.map do |f|
163 Setting::DATE_FORMATS.map do |f|
@@ -432,8 +432,11 class Issue < ActiveRecord::Base
432 if priority_derived?
432 if priority_derived?
433 names -= %w(priority_id)
433 names -= %w(priority_id)
434 end
434 end
435 if done_ratio_derived?
436 names -= %w(done_ratio)
437 end
435 unless leaf?
438 unless leaf?
436 names -= %w(done_ratio estimated_hours)
439 names -= %w(estimated_hours)
437 end
440 end
438 names
441 names
439 end
442 end
@@ -1161,6 +1164,10 class Issue < ActiveRecord::Base
1161 !leaf? && Setting.parent_issue_priority == 'derived'
1164 !leaf? && Setting.parent_issue_priority == 'derived'
1162 end
1165 end
1163
1166
1167 def done_ratio_derived?
1168 !leaf? && Setting.parent_issue_done_ratio == 'derived'
1169 end
1170
1164 def <=>(issue)
1171 def <=>(issue)
1165 if issue.nil?
1172 if issue.nil?
1166 -1
1173 -1
@@ -1463,19 +1470,21 class Issue < ActiveRecord::Base
1463 end
1470 end
1464 end
1471 end
1465
1472
1466 # done ratio = weighted average ratio of leaves
1473 if p.done_ratio_derived?
1467 unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
1474 # done ratio = weighted average ratio of leaves
1468 leaves_count = p.leaves.count
1475 unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
1469 if leaves_count > 0
1476 leaves_count = p.leaves.count
1470 average = p.leaves.where("estimated_hours > 0").average(:estimated_hours).to_f
1477 if leaves_count > 0
1471 if average == 0
1478 average = p.leaves.where("estimated_hours > 0").average(:estimated_hours).to_f
1472 average = 1
1479 if average == 0
1480 average = 1
1481 end
1482 done = p.leaves.joins(:status).
1483 sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
1484 "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
1485 progress = done / (average * leaves_count)
1486 p.done_ratio = progress.round
1473 end
1487 end
1474 done = p.leaves.joins(:status).
1475 sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
1476 "* (CASE WHEN is_closed = #{self.class.connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)").to_f
1477 progress = done / (average * leaves_count)
1478 p.done_ratio = progress.round
1479 end
1488 end
1480 end
1489 end
1481
1490
@@ -28,6 +28,8
28 <p><%= setting_select :parent_issue_dates, parent_issue_dates_options, :label => "#{l(:field_start_date)} / #{l(:field_due_date)}" %></p>
28 <p><%= setting_select :parent_issue_dates, parent_issue_dates_options, :label => "#{l(:field_start_date)} / #{l(:field_due_date)}" %></p>
29
29
30 <p><%= setting_select :parent_issue_priority, parent_issue_priority_options, :label => :field_priority %></p>
30 <p><%= setting_select :parent_issue_priority, parent_issue_priority_options, :label => :field_priority %></p>
31
32 <p><%= setting_select :parent_issue_done_ratio, parent_issue_done_ratio_options, :label => :field_done_ratio %></p>
31 </div>
33 </div>
32 </fieldset>
34 </fieldset>
33
35
@@ -150,6 +150,8 parent_issue_dates:
150 default: 'derived'
150 default: 'derived'
151 parent_issue_priority:
151 parent_issue_priority:
152 default: 'derived'
152 default: 'derived'
153 parent_issue_done_ratio:
154 default: 'derived'
153 link_copied_issue:
155 link_copied_issue:
154 default: 'ask'
156 default: 'ask'
155 issue_group_assignment:
157 issue_group_assignment:
@@ -287,40 +287,6 class IssueNestedSetTest < ActiveSupport::TestCase
287 end
287 end
288 end
288 end
289
289
290 def test_parent_done_ratio_should_be_average_done_ratio_of_leaves
291 parent = Issue.generate!
292 parent.generate_child!(:done_ratio => 20)
293 assert_equal 20, parent.reload.done_ratio
294 parent.generate_child!(:done_ratio => 70)
295 assert_equal 45, parent.reload.done_ratio
296
297 child = parent.generate_child!(:done_ratio => 0)
298 assert_equal 30, parent.reload.done_ratio
299
300 child.generate_child!(:done_ratio => 30)
301 assert_equal 30, child.reload.done_ratio
302 assert_equal 40, parent.reload.done_ratio
303 end
304
305 def test_parent_done_ratio_should_be_weighted_by_estimated_times_if_any
306 parent = Issue.generate!
307 parent.generate_child!(:estimated_hours => 10, :done_ratio => 20)
308 assert_equal 20, parent.reload.done_ratio
309 parent.generate_child!(:estimated_hours => 20, :done_ratio => 50)
310 assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
311 end
312
313 def test_parent_done_ratio_with_child_estimate_to_0_should_reach_100
314 parent = Issue.generate!
315 issue1 = parent.generate_child!
316 issue2 = parent.generate_child!(:estimated_hours => 0)
317 assert_equal 0, parent.reload.done_ratio
318 issue1.reload.close!
319 assert_equal 50, parent.reload.done_ratio
320 issue2.reload.close!
321 assert_equal 100, parent.reload.done_ratio
322 end
323
324 def test_parent_estimate_should_be_sum_of_leaves
290 def test_parent_estimate_should_be_sum_of_leaves
325 parent = Issue.generate!
291 parent = Issue.generate!
326 parent.generate_child!(:estimated_hours => nil)
292 parent.generate_child!(:estimated_hours => nil)
@@ -97,6 +97,54 class IssueSubtaskingTest < ActiveSupport::TestCase
97 end
97 end
98 end
98 end
99
99
100 def test_parent_done_ratio_should_be_read_only_with_parent_issue_done_ratio_set_to_derived
101 with_settings :parent_issue_done_ratio => 'derived' do
102 issue = Issue.generate_with_child!
103 user = User.find(1)
104 assert !issue.safe_attribute?('done_ratio', user)
105 end
106 end
107
108 def test_parent_done_ratio_should_be_average_done_ratio_of_leaves
109 with_settings :parent_issue_done_ratio => 'derived' do
110 parent = Issue.generate!
111 parent.generate_child!(:done_ratio => 20)
112 assert_equal 20, parent.reload.done_ratio
113 parent.generate_child!(:done_ratio => 70)
114 assert_equal 45, parent.reload.done_ratio
115
116 child = parent.generate_child!(:done_ratio => 0)
117 assert_equal 30, parent.reload.done_ratio
118
119 child.generate_child!(:done_ratio => 30)
120 assert_equal 30, child.reload.done_ratio
121 assert_equal 40, parent.reload.done_ratio
122 end
123 end
124
125 def test_parent_done_ratio_should_be_weighted_by_estimated_times_if_any
126 with_settings :parent_issue_done_ratio => 'derived' do
127 parent = Issue.generate!
128 parent.generate_child!(:estimated_hours => 10, :done_ratio => 20)
129 assert_equal 20, parent.reload.done_ratio
130 parent.generate_child!(:estimated_hours => 20, :done_ratio => 50)
131 assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
132 end
133 end
134
135 def test_parent_done_ratio_with_child_estimate_to_0_should_reach_100
136 with_settings :parent_issue_done_ratio => 'derived' do
137 parent = Issue.generate!
138 issue1 = parent.generate_child!
139 issue2 = parent.generate_child!(:estimated_hours => 0)
140 assert_equal 0, parent.reload.done_ratio
141 issue1.reload.close!
142 assert_equal 50, parent.reload.done_ratio
143 issue2.reload.close!
144 assert_equal 100, parent.reload.done_ratio
145 end
146 end
147
100 def test_parent_dates_should_be_editable_with_parent_issue_dates_set_to_independent
148 def test_parent_dates_should_be_editable_with_parent_issue_dates_set_to_independent
101 with_settings :parent_issue_dates => 'independent' do
149 with_settings :parent_issue_dates => 'independent' do
102 issue = Issue.generate_with_child!
150 issue = Issue.generate_with_child!
@@ -143,4 +191,20 class IssueSubtaskingTest < ActiveSupport::TestCase
143 assert_equal 'Normal', parent.reload.priority.name
191 assert_equal 'Normal', parent.reload.priority.name
144 end
192 end
145 end
193 end
194
195 def test_parent_done_ratio_should_be_editable_with_parent_issue_done_ratio_set_to_independent
196 with_settings :parent_issue_done_ratio => 'independent' do
197 issue = Issue.generate_with_child!
198 user = User.find(1)
199 assert issue.safe_attribute?('done_ratio', user)
200 end
201 end
202
203 def test_parent_done_ratio_should_not_be_updated_with_parent_issue_done_ratio_set_to_independent
204 with_settings :parent_issue_done_ratio => 'independent' do
205 parent = Issue.generate!(:done_ratio => 0)
206 child1 = parent.generate_child!(:done_ratio => 10)
207 assert_equal 0, parent.reload.done_ratio
208 end
209 end
146 end
210 end
General Comments 0
You need to be logged in to leave comments. Login now