##// END OF EJS Templates
Display status change before subject of issue on the activity view otherwise it may be truncated....
Display status change before subject of issue on the activity view otherwise it may be truncated. git-svn-id: http://redmine.rubyforge.org/svn/trunk@1505 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r1474:7042879811ab
r1491:2e8b2d5e1312
Show More
issue.rb
256 lines | 9.1 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
has_many :attachments, :as => :container, :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
added svn:eol-style native property on /app files...
r330 has_many :custom_values, :dependent => :delete_all, :as => :customized
has_many :custom_fields, :through => :custom_values
Jean-Philippe Lang
Commit messages are now scanned for referenced or fixed issue IDs....
r470 has_and_belongs_to_many :changesets, :order => "revision ASC"
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
Added "Watch" functionality on issues. It allows users to receive mail notifications about issue changes....
r450 acts_as_watchable
Jean-Philippe Lang
Ability to search all projects or the projects the user belongs to (#791)....
r1420 acts_as_searchable :columns => ['subject', "#{table_name}.description"], :include => :project, :with => {:journal => :issue}
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
Search engines now supports pagination....
r755 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
Jean-Philippe Lang
Added "Watch" functionality on issues. It allows users to receive mail notifications about issue changes....
r450
Jean-Philippe Lang
Added per-project tracker selection. Trackers can be selected on project settings....
r907 validates_presence_of :subject, :description, :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 validates_associated :custom_values, :on => :update
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
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
Fixed: Update of time entry fails when the issue has been moved to an other project....
r896 # Move an issue to a new project and tracker
def move_to(new_project, new_tracker = nil)
transaction do
if new_project && project_id != new_project.id
# 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?
self.relations_from.clear
self.relations_to.clear
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
self.category = nil
self.fixed_version = nil
self.project = new_project
end
if new_tracker
self.tracker = new_tracker
end
if save
# Manually update project_id on related time entries
TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
else
rollback_db_transaction
return false
end
end
return true
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 custom_value_for(custom_field)
self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
return nil
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 }
@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
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
def self.visible_by(usr)
with_scope(:find => { :conditions => Project.visible_by(usr) }) do
yield
end
end
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
Initial commit...
r2 end