]> source.dussan.org Git - redmine.git/commitdiff
Moves issue calculations into the fixed_issues relation (#27676).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Wed, 29 Nov 2017 19:36:13 +0000 (19:36 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Wed, 29 Nov 2017 19:36:13 +0000 (19:36 +0000)
This way, we can reuse them on refined relations,
e.g. @version.fixed_issues.closed_count@ vs. @version.fixed_issues.visible.closed_count@

Patch by Gregor Schmidt.

git-svn-id: http://svn.redmine.org/redmine/trunk@17050 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/version.rb

index 4c559dcadac27d311ed09c301277f38ad136d5fb..12a7be90379670816bbde9df0da72b529b06313a 100644 (file)
@@ -23,7 +23,97 @@ class Version < ActiveRecord::Base
   before_destroy :nullify_projects_default_version
 
   belongs_to :project
-  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
+  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify do
+    # Returns the total estimated time for this version
+    # (sum of leaves estimated_hours)
+    def estimated_hours
+      @estimated_hours ||= sum(:estimated_hours).to_f
+    end
+    #
+    # Returns the total amount of open issues for this version.
+    def open_count
+      load_counts
+      @open_count
+    end
+
+    # Returns the total amount of closed issues for this version.
+    def closed_count
+      load_counts
+      @closed_count
+    end
+
+    # Returns the completion percentage of this version based on the amount of open/closed issues
+    # and the time spent on the open issues.
+    def completed_percent
+      if count == 0
+        0
+      elsif open_count == 0
+        100
+      else
+        issues_progress(false) + issues_progress(true)
+      end
+    end
+
+    # Returns the percentage of issues that have been marked as 'closed'.
+    def closed_percent
+      if count == 0
+        0
+      else
+        issues_progress(false)
+      end
+    end
+
+    private
+
+    def load_counts
+      unless @open_count
+        @open_count = 0
+        @closed_count = 0
+        self.group(:status).count.each do |status, count|
+          if status.is_closed?
+            @closed_count += count
+          else
+            @open_count += count
+          end
+        end
+      end
+    end
+
+    # Returns the average estimated time of assigned issues
+    # or 1 if no issue has an estimated time
+    # Used to weight unestimated issues in progress calculation
+    def estimated_average
+      if @estimated_average.nil?
+        average = average(:estimated_hours).to_f
+        if average == 0
+          average = 1
+        end
+        @estimated_average = average
+      end
+      @estimated_average
+    end
+
+    # Returns the total progress of open or closed issues.  The returned percentage takes into account
+    # the amount of estimated time set for this version.
+    #
+    # Examples:
+    # issues_progress(true)   => returns the progress percentage for open issues.
+    # issues_progress(false)  => returns the progress percentage for closed issues.
+    def issues_progress(open)
+      @issues_progress ||= {}
+      @issues_progress[open] ||= begin
+        progress = 0
+        if count > 0
+          ratio = open ? 'done_ratio' : 100
+
+          done = open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f
+          progress = done / (estimated_average * count)
+        end
+        progress
+      end
+    end
+  end
+
   acts_as_customizable
   acts_as_attachable :view_permission => :view_files,
                      :edit_permission => :manage_files,
@@ -104,7 +194,7 @@ class Version < ActiveRecord::Base
   # Returns the total estimated time for this version
   # (sum of leaves estimated_hours)
   def estimated_hours
-    @estimated_hours ||= fixed_issues.sum(:estimated_hours).to_f
+    fixed_issues.estimated_hours
   end
 
   # Returns the total reported time for this version
@@ -139,22 +229,12 @@ class Version < ActiveRecord::Base
   # Returns the completion percentage of this version based on the amount of open/closed issues
   # and the time spent on the open issues.
   def completed_percent
-    if issues_count == 0
-      0
-    elsif open_issues_count == 0
-      100
-    else
-      issues_progress(false) + issues_progress(true)
-    end
+    fixed_issues.completed_percent
   end
 
   # Returns the percentage of issues that have been marked as 'closed'.
   def closed_percent
-    if issues_count == 0
-      0
-    else
-      issues_progress(false)
-    end
+    fixed_issues.closed_percent
   end
 
   # Returns true if the version is overdue: due date reached and some open issues
@@ -164,20 +244,17 @@ class Version < ActiveRecord::Base
 
   # Returns assigned issues count
   def issues_count
-    load_issue_counts
-    @issue_count
+    fixed_issues.count
   end
 
   # Returns the total amount of open issues for this version.
   def open_issues_count
-    load_issue_counts
-    @open_issues_count
+    fixed_issues.open_count
   end
 
   # Returns the total amount of closed issues for this version.
   def closed_issues_count
-    load_issue_counts
-    @closed_issues_count
+    fixed_issues.closed_count
   end
 
   def wiki_page
@@ -284,21 +361,6 @@ class Version < ActiveRecord::Base
 
   private
 
-  def load_issue_counts
-    unless @issue_count
-      @open_issues_count = 0
-      @closed_issues_count = 0
-      fixed_issues.group(:status).count.each do |status, count|
-        if status.is_closed?
-          @closed_issues_count += count
-        else
-          @open_issues_count += count
-        end
-      end
-      @issue_count = @open_issues_count + @closed_issues_count
-    end
-  end
-
   # Update the issue's fixed versions. Used if a version's sharing changes.
   def update_issues_from_sharing_change
     if saved_change_to_sharing?
@@ -316,40 +378,6 @@ class Version < ActiveRecord::Base
     end
   end
 
-  # Returns the average estimated time of assigned issues
-  # or 1 if no issue has an estimated time
-  # Used to weight unestimated issues in progress calculation
-  def estimated_average
-    if @estimated_average.nil?
-      average = fixed_issues.average(:estimated_hours).to_f
-      if average == 0
-        average = 1
-      end
-      @estimated_average = average
-    end
-    @estimated_average
-  end
-
-  # Returns the total progress of open or closed issues.  The returned percentage takes into account
-  # the amount of estimated time set for this version.
-  #
-  # Examples:
-  # issues_progress(true)   => returns the progress percentage for open issues.
-  # issues_progress(false)  => returns the progress percentage for closed issues.
-  def issues_progress(open)
-    @issues_progress ||= {}
-    @issues_progress[open] ||= begin
-      progress = 0
-      if issues_count > 0
-        ratio = open ? 'done_ratio' : 100
-
-        done = fixed_issues.open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f
-        progress = done / (estimated_average * issues_count)
-      end
-      progress
-    end
-  end
-
   def referenced_by_a_custom_field?
     CustomValue.joins(:custom_field).
       where(:value => id.to_s, :custom_fields => {:field_format => 'version'}).any?