##// END OF EJS Templates
Updates 0.8.1 CHANGELOG....
Updates 0.8.1 CHANGELOG. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2468 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r2357:b11a1d852c37
r2407:13e2c727cfa7
Show More
issue.rb
292 lines | 10.8 KiB | text/x-ruby | RubyLexer
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # redMine - project management software
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503 # Copyright (C) 2006-2007 Jean-Philippe Lang
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 #
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base
belongs_to :project
belongs_to :tracker
belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
has_many :journals, :as => :journalized, :dependent => :destroy
Jean-Philippe Lang
Let the user choose when deleting issues with reported hours (closes #734, #71):...
r1168 has_many :time_entries, :dependent => :delete_all
Jean-Philippe Lang
Fixed: associated revisions are displayed in wrong order on issue view (#1546)....
r1582 has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC"
Jean-Philippe Lang
Commit messages are now scanned for referenced or fixed issue IDs....
r470
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503 has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
Jean-Philippe Lang
AttachmentsController now handles attachments deletion....
r2114 acts_as_attachable :after_remove => :attachment_removed
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 acts_as_customizable
Jean-Philippe Lang
Added "Watch" functionality on issues. It allows users to receive mail notifications about issue changes....
r450 acts_as_watchable
Jean-Philippe Lang
Search engine: display total results count (#906) and count by result type....
r1664 acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"],
:include => [:project, :journals],
# sort by id so that limited eager loading doesn't break with postgresql
:order_column => "#{table_name}.id"
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"},
Jean-Philippe Lang
Different icon for closed issues in search result (#992)....
r2254 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}},
:type => Proc.new {|o| 'issue' + (o.closed? ? ' closed' : '') }
Jean-Philippe Lang
Added "Watch" functionality on issues. It allows users to receive mail notifications about issue changes....
r450
Jean-Philippe Lang
Display latest user's activity on account/show view....
r2064 acts_as_activity_provider :find_options => {:include => [:project, :author, :tracker]},
:author_key => :author_id
Jean-Philippe Lang
Activity refactoring....
r1692
Jean-Philippe Lang
Makes issue description a non-required field (#2456)....
r2244 validates_presence_of :subject, :priority, :project, :tracker, :author, :status
Jean-Philippe Lang
Added several validates_length_of...
r590 validates_length_of :subject, :maximum => 255
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 validates_inclusion_of :done_ratio, :in => 0..100
Jean-Philippe Lang
Added 'Estimated hours' attribute on issues....
r720 validates_numericality_of :estimated_hours, :allow_nil => true
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
Fixed that 'My page' blocks may display issues that the user is no longer allowed to view (#2590)....
r2320 named_scope :visible, lambda {|*args| { :include => :project,
:conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } }
Jean-Philippe Lang
Fixed: issue details view discloses relations to issues that the user is not allowed to view (#2589)....
r2341 # Returns true if usr or current user is allowed to view the issue
def visible?(usr=nil)
(usr || User.current).allowed_to?(:view_issues, self.project)
end
Jean-Philippe Lang
Added default value for enumerations....
r792 def after_initialize
if new_record?
# set default values for new records only
self.status ||= IssueStatus.default
self.priority ||= Enumeration.default('IPRI')
end
end
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 # Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
def available_custom_fields
(project && tracker) ? project.all_issue_custom_fields.select {|c| tracker.custom_fields.include? c } : []
end
Jean-Philippe Lang
Added the hability to copy an issue....
r860 def copy_from(arg)
issue = arg.is_a?(Issue) ? arg : Issue.find(arg)
self.attributes = issue.attributes.dup
self.custom_values = issue.custom_values.collect {|v| v.clone}
self
end
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 # Moves/copies an issue to a new project and tracker
# Returns the moved/copied issue on success, false on failure
def move_to(new_project, new_tracker = nil, options = {})
options ||= {}
issue = options[:copy] ? self.clone : self
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 transaction do
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 if new_project && issue.project_id != new_project.id
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 # delete issue relations
Jean-Philippe Lang
Do not clear issue relations when moving an issue to another project if cross-project issue relations are allowed (closes #696)....
r1150 unless Setting.cross_project_issue_relations?
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 issue.relations_from.clear
issue.relations_to.clear
Jean-Philippe Lang
Do not clear issue relations when moving an issue to another project if cross-project issue relations are allowed (closes #696)....
r1150 end
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 # issue is moved to another project
Jean-Philippe Lang
When moving an issue to another project, reassign it to the category with same name if any (#1653)....
r1688 # reassign to the category with same name if any
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 new_category = issue.category.nil? ? nil : new_project.issue_categories.find_by_name(issue.category.name)
issue.category = new_category
issue.fixed_version = nil
issue.project = new_project
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 end
if new_tracker
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 issue.tracker = new_tracker
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 end
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 if options[:copy]
issue.custom_field_values = self.custom_field_values.inject({}) {|h,v| h[v.custom_field_id] = v.value; h}
issue.status = self.status
end
if issue.save
unless options[:copy]
# Manually update project_id on related time entries
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
end
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 else
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 Issue.connection.rollback_db_transaction
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 return false
end
end
Jean-Philippe Lang
Adds ability to bulk copy issues (#1847)....
r2311 return issue
Jean-Philippe Lang
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 end
Jean-Philippe Lang
Added default value for enumerations....
r792 def priority_id=(pid)
self.priority = nil
write_attribute(:priority_id, pid)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Estimated time recognizes improved time formats (#1092)....
r1346
def estimated_hours=(h)
write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def validate
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
errors.add :due_date, :activerecord_error_not_a_date
end
if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :activerecord_error_greater_than_start_date
end
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503
if start_date && soonest_start && start_date < soonest_start
errors.add :start_date, :activerecord_error_invalid
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Added per-project tracker selection. Trackers can be selected on project settings....
r907 def validate_on_create
errors.add :tracker_id, :activerecord_error_invalid unless project.trackers.include?(tracker)
end
Jean-Philippe Lang
Each category can now be associated to a user, so that new issues in that category are automatically assigned to that user....
r574 def before_create
# default assignment based on category
if assigned_to.nil? && category && category.assigned_to
self.assigned_to = category.assigned_to
end
end
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503 def before_save
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 if @current_journal
# attributes changes
(Issue.column_names - %w(id description)).each {|c|
@current_journal.details << JournalDetail.new(:property => 'attr',
:prop_key => c,
:old_value => @issue_before_change.send(c),
:value => send(c)) unless send(c)==@issue_before_change.send(c)
}
# custom fields changes
custom_values.each {|c|
Jean-Philippe Lang
Fixed: custom field displayed as deleted in the issue history even if no value was set....
r695 next if (@custom_values_before_change[c.custom_field_id]==c.value ||
(@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?))
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 @current_journal.details << JournalDetail.new(:property => 'cf',
:prop_key => c.custom_field_id,
:old_value => @custom_values_before_change[c.custom_field_id],
Jean-Philippe Lang
Fixed: custom field displayed as deleted in the issue history even if no value was set....
r695 :value => c.value)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 }
Jean-Philippe Lang
Fixed: unable to add a file to an issue without entering a note....
r840 @current_journal.save
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Fixed: unable to add a file to an issue without entering a note....
r840 # Save the issue even if the journal is not saved (because empty)
true
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503 def after_save
Jean-Philippe Lang
Fixed: auto closing of duplicates doesn't work....
r1148 # Reload is needed in order to get the right status
reload
Jean-Philippe Lang
Automatic closing of duplicate issues....
r657 # Update start/due dates of following issues
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503 relations_from.each(&:set_issue_to_dates)
Jean-Philippe Lang
Automatic closing of duplicate issues....
r657
# Close duplicates if the issue was closed
if @issue_before_change && !@issue_before_change.closed? && self.closed?
duplicates.each do |duplicate|
Jean-Philippe Lang
Fixed: ActiveRecord::StaleObjectError exception on closing a set of circular duplicate issues (#1105)....
r1345 # Reload is need in case the duplicate was updated by a previous duplicate
duplicate.reload
Jean-Philippe Lang
Automatic closing of duplicate issues....
r657 # Don't re-close it if it's already closed
next if duplicate.closed?
# Same user and notes
duplicate.init_journal(@current_journal.user, @current_journal.notes)
duplicate.update_attribute :status, self.status
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def init_journal(user, notes = "")
@current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
@issue_before_change = self.clone
Jean-Philippe Lang
Fixed: auto closing of duplicates doesn't work....
r1148 @issue_before_change.status = self.status
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 @custom_values_before_change = {}
self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
Jean-Philippe Lang
Fixed: Issue updated_on is not updated when a user adds a note with no edit privilege....
r1757 # Make sure updated_on is updated when adding a note.
updated_on_will_change!
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 @current_journal
end
Jean-Philippe Lang
Simple time tracking functionality added. Time can be logged at issue or project level....
r365
Jean-Philippe Lang
Automatic closing of duplicate issues....
r657 # Return true if the issue is closed, otherwise false
def closed?
self.status.is_closed?
end
Jean-Philippe Lang
Adds a css class (overdue) to overdue issues on issue lists and detail views (#2337)....
r2138 # Returns true if the issue is overdue
def overdue?
Jean-Philippe Lang
Closed issue are not overdue, fixes r2140 (#2337)....
r2357 !due_date.nil? && (due_date < Date.today) && !status.is_closed?
Jean-Philippe Lang
Adds a css class (overdue) to overdue issues on issue lists and detail views (#2337)....
r2138 end
Jean-Philippe Lang
Added a 'Assignable' boolean on Role model....
r643 # Users the issue can be assigned to
def assignable_users
Jean-Philippe Lang
Added 'Bulk edit' functionality....
r806 project.assignable_users
Jean-Philippe Lang
Added a 'Assignable' boolean on Role model....
r643 end
Jean-Philippe Lang
Merged IssuesController change_status and add_note actions....
r1030 # Returns an array of status that user is able to apply
def new_statuses_allowed_to(user)
statuses = status.find_new_statuses_allowed_to(user.role_for_project(project), tracker)
statuses << status unless statuses.empty?
statuses.uniq.sort
end
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 # Returns the mail adresses of users that should be notified for the issue
def recipients
recipients = project.recipients
Jean-Philippe Lang
Fixed: locked users should not receive email notifications....
r1061 # Author and assignee are always notified unless they have been locked
recipients << author.mail if author && author.active?
recipients << assigned_to.mail if assigned_to && assigned_to.active?
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 recipients.compact.uniq
end
Jean-Philippe Lang
Simple time tracking functionality added. Time can be logged at issue or project level....
r365 def spent_hours
@spent_hours ||= time_entries.sum(:hours) || 0
end
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503
def relations
(relations_from + relations_to).sort
end
def all_dependent_issues
dependencies = []
relations_from.each do |relation|
dependencies << relation.issue_to
dependencies += relation.issue_to.all_dependent_issues
end
dependencies
end
Jean-Philippe Lang
Make the 'duplicates of' relation asymmetric:...
r1474 # Returns an array of issues that duplicate this one
Jean-Philippe Lang
Automatic closing of duplicate issues....
r657 def duplicates
Jean-Philippe Lang
Make the 'duplicates of' relation asymmetric:...
r1474 relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from}
Jean-Philippe Lang
Automatic closing of duplicate issues....
r657 end
Jean-Philippe Lang
Gantt chart: display issues that don't have a due date if they are assigned to a version with a date (#184)....
r1441 # Returns the due date or the target due date if any
# Used on gantt chart
def due_before
due_date || (fixed_version ? fixed_version.effective_date : nil)
end
Jean-Philippe Lang
Issue relations first commit (not thoroughly tested). 4 kinds of relation are available:...
r503 def duration
(start_date && due_date) ? due_date - start_date : 0
end
def soonest_start
@soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
end
Jean-Philippe Lang
Include subprojects on the issue list, calendar and gantt by default....
r1164
Jean-Philippe Lang
Time report can be done at issue level (closes #970) + timelog views xhtml validation....
r1304 def to_s
"#{tracker} ##{id}: #{subject}"
end
Jean-Philippe Lang
AttachmentsController now handles attachments deletion....
r2114
private
# Callback on attachment deletion
def attachment_removed(obj)
journal = init_journal(User.current)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => obj.id,
:old_value => obj.filename)
journal.save
end
Jean-Philippe Lang
Initial commit...
r2 end