Project

General

Profile

Patch #30115 » redmine_version_relation_extension_in_module_svn.patch

Jérôme BATAILLE, 2018-12-06 12:37

View differences:

app/models/version.rb
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18
class Version < ActiveRecord::Base
19
  include Redmine::SafeAttributes
20

  
21
  after_update :update_issues_from_sharing_change
22
  after_save :update_default_project_version
23
  before_destroy :nullify_projects_default_version
18
module FixedIssuesExtension
19
  # Returns the total estimated time for this version
20
  # (sum of leaves estimated_hours)
21
  def estimated_hours
22
    @estimated_hours ||= sum(:estimated_hours).to_f
23
  end
24
  #
25
  # Returns the total amount of open issues for this version.
26
  def open_count
27
    load_counts
28
    @open_count
29
  end
24 30

  
25
  belongs_to :project
26
  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify do
27
    # Returns the total estimated time for this version
28
    # (sum of leaves estimated_hours)
29
    def estimated_hours
30
      @estimated_hours ||= sum(:estimated_hours).to_f
31
    end
32
    #
33
    # Returns the total amount of open issues for this version.
34
    def open_count
35
      load_counts
36
      @open_count
37
    end
31
  # Returns the total amount of closed issues for this version.
32
  def closed_count
33
    load_counts
34
    @closed_count
35
  end
38 36

  
39
    # Returns the total amount of closed issues for this version.
40
    def closed_count
41
      load_counts
42
      @closed_count
37
  # Returns the completion percentage of this version based on the amount of open/closed issues
38
  # and the time spent on the open issues.
39
  def completed_percent
40
    if count == 0
41
      0
42
    elsif open_count == 0
43
      100
44
    else
45
      issues_progress(false) + issues_progress(true)
43 46
    end
47
  end
44 48

  
45
    # Returns the completion percentage of this version based on the amount of open/closed issues
46
    # and the time spent on the open issues.
47
    def completed_percent
48
      if count == 0
49
        0
50
      elsif open_count == 0
51
        100
52
      else
53
        issues_progress(false) + issues_progress(true)
54
      end
49
  # Returns the percentage of issues that have been marked as 'closed'.
50
  def closed_percent
51
    if count == 0
52
      0
53
    else
54
      issues_progress(false)
55 55
    end
56
  end
56 57

  
57
    # Returns the percentage of issues that have been marked as 'closed'.
58
    def closed_percent
59
      if count == 0
60
        0
61
      else
62
        issues_progress(false)
63
      end
64
    end
58
  private
65 59

  
66
    private
67

  
68
    def load_counts
69
      unless @open_count
70
        @open_count = 0
71
        @closed_count = 0
72
        self.group(:status).count.each do |status, count|
73
          if status.is_closed?
74
            @closed_count += count
75
          else
76
            @open_count += count
77
          end
60
  def load_counts
61
    unless @open_count
62
      @open_count = 0
63
      @closed_count = 0
64
      self.group(:status).count.each do |status, count|
65
        if status.is_closed?
66
          @closed_count += count
67
        else
68
          @open_count += count
78 69
        end
79 70
      end
80 71
    end
72
  end
81 73

  
82
    # Returns the average estimated time of assigned issues
83
    # or 1 if no issue has an estimated time
84
    # Used to weight unestimated issues in progress calculation
85
    def estimated_average
86
      if @estimated_average.nil?
87
        average = average(:estimated_hours).to_f
88
        if average == 0
89
          average = 1
90
        end
91
        @estimated_average = average
74
  # Returns the average estimated time of assigned issues
75
  # or 1 if no issue has an estimated time
76
  # Used to weight unestimated issues in progress calculation
77
  def estimated_average
78
    if @estimated_average.nil?
79
      average = average(:estimated_hours).to_f
80
      if average == 0
81
        average = 1
92 82
      end
93
      @estimated_average
83
      @estimated_average = average
94 84
    end
95

  
96
    # Returns the total progress of open or closed issues.  The returned percentage takes into account
97
    # the amount of estimated time set for this version.
98
    #
99
    # Examples:
100
    # issues_progress(true)   => returns the progress percentage for open issues.
101
    # issues_progress(false)  => returns the progress percentage for closed issues.
102
    def issues_progress(open)
103
      @issues_progress ||= {}
104
      @issues_progress[open] ||= begin
105
        progress = 0
106
        if count > 0
107
          ratio = open ? 'done_ratio' : 100
108

  
109
          done = open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f
110
          progress = done / (estimated_average * count)
111
        end
112
        progress
85
    @estimated_average
86
  end
87

  
88
  # Returns the total progress of open or closed issues.  The returned percentage takes into account
89
  # the amount of estimated time set for this version.
90
  #
91
  # Examples:
92
  # issues_progress(true)   => returns the progress percentage for open issues.
93
  # issues_progress(false)  => returns the progress percentage for closed issues.
94
  def issues_progress(open)
95
    @issues_progress ||= {}
96
    @issues_progress[open] ||= begin
97
      progress = 0
98
      if count > 0
99
        ratio = open ? 'done_ratio' : 100
100

  
101
        done = open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f
102
        progress = done / (estimated_average * count)
113 103
      end
104
      progress
114 105
    end
115 106
  end
107
end
108

  
109
class Version < ActiveRecord::Base
110
  include Redmine::SafeAttributes
111

  
112
  after_update :update_issues_from_sharing_change
113
  after_save :update_default_project_version
114
  before_destroy :nullify_projects_default_version
115

  
116
  belongs_to :project
117
  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify, :extend => FixedIssuesExtension
116 118

  
117 119
  acts_as_customizable
118 120
  acts_as_attachable :view_permission => :view_files,
(2-2/2)