Index: app/helpers/versions_helper.rb =================================================================== --- app/helpers/versions_helper.rb (revision 1900) +++ app/helpers/versions_helper.rb (working copy) @@ -26,12 +26,21 @@ h = Hash.new {|k,v| k[v] = [0, 0]} begin # Total issue count - Issue.count(:group => criteria, - :conditions => ["#{Issue.table_name}.fixed_version_id = ?", version.id]).each {|c,s| h[c][0] = s} - # Open issues count - Issue.count(:group => criteria, - :include => :status, - :conditions => ["#{Issue.table_name}.fixed_version_id = ? AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s} + if version.children.count > 0 + Issue.count(:group => criteria, + :conditions => ["#{Issue.table_name}.fixed_version_id = ? OR #{Issue.table_name}.fixed_version_id IN (#{version.children.collect{|p| p.id}.join(',')})", version.id]).each {|c,s| h[c][0] = s} + # Open issues count + Issue.count(:group => criteria, + :include => :status, + :conditions => ["(#{Issue.table_name}.fixed_version_id = ? OR #{Issue.table_name}.fixed_version_id IN (#{version.children.collect{|p| p.id}.join(',')})) AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s} + else + Issue.count(:group => criteria, + :conditions => ["#{Issue.table_name}.fixed_version_id = ?", version.id]).each {|c,s| h[c][0] = s} + # Open issues count + Issue.count(:group => criteria, + :include => :status, + :conditions => ["#{Issue.table_name}.fixed_version_id = ? AND #{IssueStatus.table_name}.is_closed = ?", version.id, false]).each {|c,s| h[c][1] = s} + end rescue ActiveRecord::RecordNotFound # When grouping by an association, Rails throws this exception if there's no result (bug) end Index: app/models/version.rb =================================================================== --- app/models/version.rb (revision 1900) +++ app/models/version.rb (working copy) @@ -18,7 +18,9 @@ class Version < ActiveRecord::Base before_destroy :check_integrity belongs_to :project - has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id' + belongs_to :parent, :class_name => "Version", :foreign_key => "parent_version_id" + has_many :children, :class_name => "Version", :foreign_key => "parent_version_id" + has_many :fixed_issues, :class_name => 'Issue', :finder_sql => 'select distinct i.* from issues i,versions v WHERE i.fixed_version_id = #{id} OR (i.fixed_version_id = v.id AND v.parent_version_id = #{id})', :counter_sql => 'select count(distinct i.id) from issues i,versions v WHERE i.fixed_version_id = #{id} OR (i.fixed_version_id = v.id AND v.parent_version_id = #{id})' has_many :attachments, :as => :container, :dependent => :destroy validates_presence_of :name @@ -36,12 +38,18 @@ # Returns the total estimated time for this version def estimated_hours - @estimated_hours ||= fixed_issues.sum(:estimated_hours).to_f + hours = 0 + fixed_issues.each {|i| hours += i.estimated_hours.to_f} + @estimated_hours ||= hours end # Returns the total reported time for this version def spent_hours - @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f + if self.children.count > 0 + @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ? OR #{Issue.table_name}.fixed_version_id IN (#{self.children.collect{|p| p.id}.join(',')})", id]).to_f + else + @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f + end end # Returns true if the version is completed: due date reached and no open issues @@ -54,8 +62,10 @@ 0 elsif open_issues_count == 0 100 - else - (closed_issues_count * 100 + Issue.sum('done_ratio', :include => 'status', :conditions => ["fixed_version_id = ? AND is_closed = ?", id, false]).to_f) / fixed_issues.count + elsif self.children.count > 0 + (closed_issues_count * 100 + Issue.sum('done_ratio', :include => 'status', :conditions => ["(fixed_version_id = ? OR fixed_version_id IN (#{self.children.collect{|p| p.id}.join(',')})) AND is_closed = ?", id, false]).to_f) / fixed_issues.count + else + (closed_issues_count * 100 + Issue.sum('done_ratio', :include => 'status', :conditions => ["(fixed_version_id = ?) AND is_closed = ?", id, false]).to_f) / fixed_issues.count end end @@ -73,11 +83,19 @@ end def open_issues_count - @open_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, false], :include => :status) + if self.children.count > 0 + @open_issues_count ||= Issue.count(:all, :conditions => ["(fixed_version_id = ? OR fixed_version_id IN (#{self.children.collect{|p| p.id}.join(',')})) AND is_closed = ?", self.id, false], :include => :status) + else + @open_issues_count ||= Issue.count(:all, :conditions => ["(fixed_version_id = ?) AND is_closed = ?", self.id, false], :include => :status) + end end def closed_issues_count - @closed_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, true], :include => :status) + if self.children.count > 0 + @closed_issues_count ||= Issue.count(:all, :conditions => ["(fixed_version_id = ? OR fixed_version_id IN (#{self.children.collect{|p| p.id}.join(',')})) AND is_closed = ?", self.id, true], :include => :status) + else + @closed_issues_count ||= Issue.count(:all, :conditions => ["(fixed_version_id = ?) AND is_closed = ?", self.id, true], :include => :status) + end end def wiki_page Index: app/controllers/versions_controller.rb =================================================================== --- app/controllers/versions_controller.rb (revision 1900) +++ app/controllers/versions_controller.rb (working copy) @@ -23,6 +23,7 @@ end def edit + @versions = Version.find(:all, :conditions => ["id <> ? AND parent_version_id IS NULL", params[:id]]).collect{|p| [ p.name, p.id ] } if request.post? and @version.update_attributes(params[:version]) flash[:notice] = l(:notice_successful_update) redirect_to :controller => 'projects', :action => 'settings', :tab => 'versions', :id => @project Index: app/controllers/projects_controller.rb =================================================================== --- app/controllers/projects_controller.rb (revision 1900) +++ app/controllers/projects_controller.rb (working copy) @@ -180,6 +180,7 @@ # Add a new version to @project def add_version @version = @project.versions.build(params[:version]) + @versions = Version.find(:all, :conditions => ["parent_version_id IS NULL"]).collect{|p| [ p.name, p.id ] } if request.post? and @version.save flash[:notice] = l(:notice_successful_create) redirect_to :action => 'settings', :tab => 'versions', :id => @project @@ -213,7 +214,7 @@ def roadmap @trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true]) retrieve_selected_tracker_ids(@trackers) - @versions = @project.versions.sort + @versions = (@project.versions.delete_if {|x| x.parent_version_id }).sort @versions = @versions.select {|v| !v.completed? } unless params[:completed] end Index: app/views/versions/show.rhtml =================================================================== --- app/views/versions/show.rhtml (revision 1900) +++ app/views/versions/show.rhtml (working copy) @@ -2,7 +2,9 @@ <%= link_to_if_authorized l(:button_edit), {:controller => 'versions', :action => 'edit', :id => @version}, :class => 'icon icon-edit' %> -
- <%= link_to(version.closed_issues_count, :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'c', :fixed_version_id => version, :set_filter => 1) %> + <%= link_to(version.closed_issues_count, :controller => 'issues', :action => 'index', :project_id => version.project, :set_filter => 1, :fields => ["status_id", "fixed_version_id"], :operators => {:fixed_version_id => "=",:status_id => "c"}, :values => {:fixed_version_id => (version.fixed_issues.collect {|p| p.fixed_version_id} ).uniq, :status_id =>["1"]}) %> <%= lwr(:label_closed_issues, version.closed_issues_count) %> (<%= '%0.0f' % (version.closed_issues_count.to_f / version.fixed_issues.count * 100) %>%) - <%= link_to(version.open_issues_count, :controller => 'issues', :action => 'index', :project_id => version.project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1) %> + <%= link_to(version.open_issues_count, :controller => 'issues', :action => 'index', :project_id => version.project, :set_filter => 1, :fields => ["status_id", "fixed_version_id"], :operators => {:fixed_version_id => "=",:status_id => "o"}, :values => {:fixed_version_id => (version.fixed_issues.collect {|p| p.fixed_version_id} ).uniq, :status_id =>["1"]}) %> <%= lwr(:label_open_issues, version.open_issues_count)%> (<%= '%0.0f' % (version.open_issues_count.to_f / version.fixed_issues.count * 100) %>%)
Index: app/views/projects/roadmap.rhtml =================================================================== --- app/views/projects/roadmap.rhtml (revision 1900) +++ app/views/projects/roadmap.rhtml (working copy) @@ -5,17 +5,15 @@ <% else %>