Patch #13400 » issue-13400-trunk-r12075.diff
app/models/issue.rb | ||
---|---|---|
59 | 59 |
acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]}, |
60 | 60 |
:author_key => :author_id |
61 | 61 | |
62 |
DONE_RATIO_OPTIONS = %w(issue_field issue_status) |
|
62 |
DONE_RATIO_OPTIONS = %w(issue_field issue_status logged_time)
|
|
63 | 63 | |
64 | 64 |
attr_reader :current_journal |
65 | 65 |
delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true |
... | ... | |
92 | 92 |
} |
93 | 93 | |
94 | 94 |
before_create :default_assign |
95 |
before_save :close_duplicates, :update_done_ratio_from_issue_status, :force_updated_on_change, :update_closed_on |
|
95 |
before_save :close_duplicates, :update_done_ratio, |
|
96 |
:force_updated_on_change, :update_closed_on |
|
96 | 97 |
after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?} |
97 | 98 |
after_save :reschedule_following_issues, :update_nested_set_attributes, :update_parent_attributes, :create_journal |
98 | 99 |
# Should be after_create but would be called before previous after_save callbacks |
... | ... | |
543 | 544 |
private :workflow_rule_by_attribute |
544 | 545 | |
545 | 546 |
def done_ratio |
546 |
if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
|
|
547 |
if use_status_for_done_ratio?
|
|
547 | 548 |
status.default_done_ratio |
549 |
elsif use_time_for_done_ratio? |
|
550 |
if estimated_hours && estimated_hours.to_f > 0 |
|
551 |
ratio = (total_spent_hours.to_f / estimated_hours.to_f) * 100 |
|
552 |
[ratio, 100].min.to_i |
|
553 |
else |
|
554 |
0.0 |
|
555 |
end |
|
548 | 556 |
else |
549 | 557 |
read_attribute(:done_ratio) |
550 | 558 |
end |
... | ... | |
554 | 562 |
Setting.issue_done_ratio == 'issue_status' |
555 | 563 |
end |
556 | 564 | |
565 |
def use_status_for_done_ratio? |
|
566 |
Issue.use_status_for_done_ratio? && status && status.default_done_ratio |
|
567 |
end |
|
568 | ||
569 |
def self.use_time_for_done_ratio? |
|
570 |
Setting.issue_done_ratio == 'logged_time' |
|
571 |
end |
|
572 | ||
573 |
def use_time_for_done_ratio? |
|
574 |
Issue.use_time_for_done_ratio? |
|
575 |
end |
|
576 | ||
557 | 577 |
def self.use_field_for_done_ratio? |
558 | 578 |
Setting.issue_done_ratio == 'issue_field' |
559 | 579 |
end |
560 | 580 | |
581 |
def use_field_for_done_ratio? |
|
582 |
!(use_status_for_done_ratio? || use_time_for_done_ratio?) |
|
583 |
end |
|
584 | ||
561 | 585 |
def validate_issue |
562 | 586 |
if due_date && start_date && (start_date_changed? || due_date_changed?) && due_date < start_date |
563 | 587 |
errors.add :due_date, :greater_than_start_date |
... | ... | |
624 | 648 | |
625 | 649 |
# Set the done_ratio using the status if that setting is set. This will keep the done_ratios |
626 | 650 |
# even if the user turns off the setting later |
627 |
def update_done_ratio_from_issue_status
|
|
628 |
if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
|
|
629 |
self.done_ratio = status.default_done_ratio
|
|
651 |
def update_done_ratio |
|
652 |
unless use_field_for_done_ratio?
|
|
653 |
self.done_ratio = self.done_ratio
|
|
630 | 654 |
end |
631 | 655 |
end |
632 | 656 | |
657 |
def update_done_ratio! |
|
658 |
self.init_journal(User.current, "") |
|
659 |
self.update_done_ratio |
|
660 |
self.save |
|
661 |
end |
|
662 | ||
633 | 663 |
def init_journal(user, notes = "") |
634 | 664 |
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) |
635 | 665 |
if new_record? |
... | ... | |
1357 | 1387 |
end |
1358 | 1388 | |
1359 | 1389 |
# done ratio = weighted average ratio of leaves |
1360 |
unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
|
|
1390 |
if p.use_field_for_done_ratio
|
|
1361 | 1391 |
leaves_count = p.leaves.count |
1362 | 1392 |
if leaves_count > 0 |
1363 | 1393 |
average = p.leaves.average(:estimated_hours).to_f |
app/models/time_entry.rb | ||
---|---|---|
42 | 42 |
validates_length_of :comments, :maximum => 255, :allow_nil => true |
43 | 43 |
validates :spent_on, :date => true |
44 | 44 |
before_validation :set_project_if_nil |
45 |
after_save :update_done_ratio |
|
46 |
after_destroy :update_done_ratio |
|
45 | 47 |
validate :validate_time_entry |
46 | 48 | |
47 | 49 |
scope :visible, lambda {|*args| |
... | ... | |
87 | 89 |
errors.add :issue_id, :invalid if (issue_id && !issue) || (issue && project!=issue.project) |
88 | 90 |
end |
89 | 91 | |
92 |
def update_done_ratio |
|
93 |
if issue && Issue.use_time_for_done_ratio? |
|
94 |
issue.update_done_ratio! |
|
95 |
end |
|
96 |
end |
|
97 | ||
90 | 98 |
def hours=(h) |
91 | 99 |
write_attribute :hours, (h.is_a?(String) ? (h.to_hours || h) : h) |
92 | 100 |
end |
config/locales/de.yml | ||
---|---|---|
980 | 980 |
setting_issue_done_ratio: Berechne den Ticket-Fortschritt mittels |
981 | 981 |
setting_issue_done_ratio_issue_field: Ticket-Feld %-erledigt |
982 | 982 |
setting_issue_done_ratio_issue_status: Ticket-Status |
983 |
setting_issue_done_ratio_logged_time: Geschätzter und gebuchter Zeit |
|
983 | 984 |
setting_issue_group_assignment: Ticketzuweisung an Gruppen erlauben |
984 | 985 |
setting_issue_list_default_columns: Standard-Spalten in der Ticket-Auflistung |
985 | 986 |
setting_issues_export_limit: Max. Anzahl Tickets bei CSV/PDF-Export |
config/locales/en.yml | ||
---|---|---|
387 | 387 |
setting_issue_done_ratio: Calculate the issue done ratio with |
388 | 388 |
setting_issue_done_ratio_issue_field: Use the issue field |
389 | 389 |
setting_issue_done_ratio_issue_status: Use the issue status |
390 |
setting_issue_done_ratio_logged_time: Use the logged and estimated time |
|
390 | 391 |
setting_start_of_week: Start calendars on |
391 | 392 |
setting_rest_api_enabled: Enable REST web service |
392 | 393 |
setting_cache_formatted_text: Cache formatted text |
test/unit/issue_test.rb | ||
---|---|---|
2027 | 2027 |
end |
2028 | 2028 |
end |
2029 | 2029 | |
2030 |
test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
|
|
2030 |
test "#update_done_ratio should update done_ratio according to Setting.issue_done_ratio" do |
|
2031 | 2031 |
@issue = Issue.find(1) |
2032 | 2032 |
@issue_status = IssueStatus.find(1) |
2033 | 2033 |
@issue_status.update_attribute(:default_done_ratio, 50) |
... | ... | |
2036 | 2036 |
@issue_status2.update_attribute(:default_done_ratio, 0) |
2037 | 2037 | |
2038 | 2038 |
with_settings :issue_done_ratio => 'issue_field' do |
2039 |
@issue.update_done_ratio_from_issue_status
|
|
2040 |
@issue2.update_done_ratio_from_issue_status
|
|
2039 |
@issue.update_done_ratio |
|
2040 |
@issue2.update_done_ratio |
|
2041 | 2041 | |
2042 | 2042 |
assert_equal 0, @issue.read_attribute(:done_ratio) |
2043 | 2043 |
assert_equal 30, @issue2.read_attribute(:done_ratio) |
2044 | 2044 |
end |
2045 | 2045 | |
2046 | 2046 |
with_settings :issue_done_ratio => 'issue_status' do |
2047 |
@issue.update_done_ratio_from_issue_status
|
|
2048 |
@issue2.update_done_ratio_from_issue_status
|
|
2047 |
@issue.update_done_ratio |
|
2048 |
@issue2.update_done_ratio |
|
2049 | 2049 | |
2050 | 2050 |
assert_equal 50, @issue.read_attribute(:done_ratio) |
2051 | 2051 |
assert_equal 0, @issue2.read_attribute(:done_ratio) |