diff options
author | Eric Davis <edavis@littlestreamsoftware.com> | 2010-09-10 03:09:02 +0000 |
---|---|---|
committer | Eric Davis <edavis@littlestreamsoftware.com> | 2010-09-10 03:09:02 +0000 |
commit | bdb3937e0f4c8faceb463e23cb28676930ddbd9e (patch) | |
tree | 8d8a5d1b5b78b1b206363549f8635a2e3b29ff32 /app/models | |
parent | 8d52608dbad63d504ec4b48ffe5ea09cfbe95bd9 (diff) | |
download | redmine-bdb3937e0f4c8faceb463e23cb28676930ddbd9e.tar.gz redmine-bdb3937e0f4c8faceb463e23cb28676930ddbd9e.zip |
Rewrite the Gantt chart. #6276
This version of the Gantt chart supports nested charts. So Projects,
Versions, and Issues will be nested underneath their parents correctly.
Additional features:
* Move all Gantt code to Redmine::Helpers::Gantt class instead of having it in
the Gantt class, controller, and view
* Recursive and nest sub-projects
* Recursive and nest versions
* Recursive and nest issues
* Draw a line showing when a Project is active and it's progress
* Draw a line showing when a Version is active and it's progress
* Show a version's % complete
* Change the color of Projects, Versions, and Issues if they are late or
behind schedule
* Added Project#start_date and #due_date
* Added Project#completed_percent
* Use a mini-gravatar on the Gantt chart
* Added tests for the Gantt rendering
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4072 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/issue.rb | 27 | ||||
-rw-r--r-- | app/models/project.rb | 44 | ||||
-rw-r--r-- | app/models/version.rb | 12 |
3 files changed, 82 insertions, 1 deletions
diff --git a/app/models/issue.rb b/app/models/issue.rb index 7d0682df1..80db48108 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -62,10 +62,28 @@ class Issue < ActiveRecord::Base named_scope :open, :conditions => ["#{IssueStatus.table_name}.is_closed = ?", false], :include => :status - named_scope :recently_updated, :order => "#{self.table_name}.updated_on DESC" + named_scope :recently_updated, :order => "#{Issue.table_name}.updated_on DESC" named_scope :with_limit, lambda { |limit| { :limit => limit} } named_scope :on_active_project, :include => [:status, :project, :tracker], :conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"] + named_scope :for_gantt, lambda { + { + :include => [:tracker, :status, :assigned_to, :priority, :project, :fixed_version], + :order => "#{Issue.table_name}.due_date ASC, #{Issue.table_name}.start_date ASC, #{Issue.table_name}.id ASC" + } + } + + named_scope :without_version, lambda { + { + :conditions => { :fixed_version_id => nil} + } + } + + named_scope :with_query, lambda {|query| + { + :conditions => Query.merge_conditions(query.statement) + } + } before_create :default_assign before_save :reschedule_following_issues, :close_duplicates, :update_done_ratio_from_issue_status @@ -357,6 +375,13 @@ class Issue < ActiveRecord::Base def overdue? !due_date.nil? && (due_date < Date.today) && !status.is_closed? end + + # Is the amount of work done less than it should for the due date + def behind_schedule? + return false if start_date.nil? || due_date.nil? + done_date = start_date + ((due_date - start_date+1)* done_ratio/100).floor + return done_date <= Date.today + end # Users the issue can be assigned to def assignable_users diff --git a/app/models/project.rb b/app/models/project.rb index 931f89b55..5ef7915de 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -412,6 +412,50 @@ class Project < ActiveRecord::Base def short_description(length = 255) description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description end + + # The earliest start date of a project, based on it's issues and versions + def start_date + if module_enabled?(:issue_tracking) + [ + issues.minimum('start_date'), + shared_versions.collect(&:effective_date), + shared_versions.collect {|v| v.fixed_issues.minimum('start_date')} + ].flatten.compact.min + end + end + + # The latest due date of an issue or version + def due_date + if module_enabled?(:issue_tracking) + [ + issues.maximum('due_date'), + shared_versions.collect(&:effective_date), + shared_versions.collect {|v| v.fixed_issues.maximum('due_date')} + ].flatten.compact.max + end + end + + def overdue? + active? && !due_date.nil? && (due_date < Date.today) + end + + # Returns the percent completed for this project, based on the + # progress on it's versions. + def completed_percent(options={:include_subprojects => false}) + if options.delete(:include_subprojects) + total = self_and_descendants.collect(&:completed_percent).sum + + total / self_and_descendants.count + else + if versions.count > 0 + total = versions.collect(&:completed_pourcent).sum + + total / versions.count + else + 100 + end + end + end # Return true if this project is allowed to do the specified action. # action can be: diff --git a/app/models/version.rb b/app/models/version.rb index 07e66434d..c3969fe87 100644 --- a/app/models/version.rb +++ b/app/models/version.rb @@ -73,6 +73,18 @@ class Version < ActiveRecord::Base def completed? effective_date && (effective_date <= Date.today) && (open_issues_count == 0) end + + def behind_schedule? + if completed_pourcent == 100 + return false + elsif due_date && fixed_issues.present? && fixed_issues.minimum('start_date') # TODO: should use #start_date but that method is wrong... + start_date = fixed_issues.minimum('start_date') + done_date = start_date + ((due_date - start_date+1)* completed_pourcent/100).floor + return done_date <= Date.today + else + false # No issues so it's not late + end + end # Returns the completion percentage of this version based on the amount of open/closed issues # and the time spent on the open issues. |