Class: Issue
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Issue
- Defined in:
- app/models/issue.rb
Overview
redMine - project management software Copyright (C) 2006-2007 Jean-Philippe Lang
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.
Instance Method Summary (collapse)
- - (Object) after_initialize
- - (Object) after_save
- - (Object) all_dependent_issues
-
- (Object) assignable_users
Users the issue can be assigned to.
-
- (Object) available_custom_fields
Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields.
- - (Object) before_create
- - (Object) before_save
-
- (Boolean) closed?
Return true if the issue is closed, otherwise false.
- - (Object) copy_from(arg)
-
- (Object) due_before
Returns the due date or the target due date if any Used on gantt chart.
-
- (Object) duplicates
Returns an array of issues that duplicate this one.
- - (Object) duration
- - (Object) estimated_hours=(h)
- - (Object) init_journal(user, notes = "")
-
- (Object) move_to(new_project, new_tracker = nil, options = {})
Moves/copies an issue to a new project and tracker Returns the moved/copied issue on success, false on failure.
-
- (Object) new_statuses_allowed_to(user)
Returns an array of status that user is able to apply.
-
- (Boolean) overdue?
Returns true if the issue is overdue.
- - (Object) priority_id=(pid)
-
- (Object) recipients
Returns the mail adresses of users that should be notified for the issue.
- - (Object) relations
- - (Object) soonest_start
- - (Object) spent_hours
- - (Object) to_s
- - (Object) validate
- - (Object) validate_on_create
-
- (Boolean) visible?(usr = nil)
Returns true if usr or current user is allowed to view the issue.
Instance Method Details
- (Object) after_initialize
62 63 64 65 66 67 68 |
# File 'app/models/issue.rb', line 62 def after_initialize if new_record? # set default values for new records only self.status ||= IssueStatus.default self.priority ||= Enumeration.priorities.default end end |
- (Object) after_save
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/issue.rb', line 179 def after_save # Reload is needed in order to get the right status reload # Update start/due dates of following issues relations_from.each(&:set_issue_to_dates) # Close duplicates if the issue was closed if @issue_before_change && !@issue_before_change.closed? && self.closed? duplicates.each do |duplicate| # Reload is need in case the duplicate was updated by a previous duplicate duplicate.reload # 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 end |
- (Object) all_dependent_issues
250 251 252 253 254 255 256 257 |
# File 'app/models/issue.rb', line 250 def all_dependent_issues dependencies = [] relations_from.each do |relation| dependencies << relation.issue_to dependencies += relation.issue_to.all_dependent_issues end dependencies end |
- (Object) assignable_users
Users the issue can be assigned to
222 223 224 |
# File 'app/models/issue.rb', line 222 def assignable_users project.assignable_users end |
- (Object) available_custom_fields
Overrides Redmine::Acts::Customizable::InstanceMethods#available_custom_fields
71 72 73 |
# File 'app/models/issue.rb', line 71 def available_custom_fields (project && tracker) ? project.all_issue_custom_fields.select {|c| tracker.custom_fields.include? c } : [] end |
- (Object) before_create
148 149 150 151 152 153 |
# File 'app/models/issue.rb', line 148 def before_create # default assignment based on category if assigned_to.nil? && category && category.assigned_to self.assigned_to = category.assigned_to end end |
- (Object) before_save
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'app/models/issue.rb', line 155 def before_save 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| next if (@custom_values_before_change[c.custom_field_id]==c.value || (@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?)) @current_journal.details << JournalDetail.new(:property => 'cf', :prop_key => c.custom_field_id, :old_value => @custom_values_before_change[c.custom_field_id], :value => c.value) } @current_journal.save end # Save the issue even if the journal is not saved (because empty) true end |
- (Boolean) closed?
Return true if the issue is closed, otherwise false
212 213 214 |
# File 'app/models/issue.rb', line 212 def closed? self.status.is_closed? end |
- (Object) copy_from(arg)
75 76 77 78 79 80 |
# File 'app/models/issue.rb', line 75 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 |
- (Object) due_before
Returns the due date or the target due date if any Used on gantt chart
266 267 268 |
# File 'app/models/issue.rb', line 266 def due_before due_date || (fixed_version ? fixed_version.effective_date : nil) end |
- (Object) duplicates
Returns an array of issues that duplicate this one
260 261 262 |
# File 'app/models/issue.rb', line 260 def duplicates relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from} end |
- (Object) duration
270 271 272 |
# File 'app/models/issue.rb', line 270 def duration (start_date && due_date) ? due_date - start_date : 0 end |
- (Object) estimated_hours=(h)
126 127 128 |
# File 'app/models/issue.rb', line 126 def estimated_hours=(h) write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h) end |
- (Object) init_journal(user, notes = "")
200 201 202 203 204 205 206 207 208 209 |
# File 'app/models/issue.rb', line 200 def init_journal(user, notes = "") @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) @issue_before_change = self.clone @issue_before_change.status = self.status @custom_values_before_change = {} self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value } # Make sure updated_on is updated when adding a note. updated_on_will_change! @current_journal end |
- (Object) move_to(new_project, new_tracker = nil, options = {})
Moves/copies an issue to a new project and tracker Returns the moved/copied issue on success, false on failure
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'app/models/issue.rb', line 84 def move_to(new_project, new_tracker = nil, = {}) ||= {} issue = [:copy] ? self.clone : self transaction do if new_project && issue.project_id != new_project.id # delete issue relations unless Setting.cross_project_issue_relations? issue.relations_from.clear issue.relations_to.clear end # issue is moved to another project # reassign to the category with same name if any 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 end if new_tracker issue.tracker = new_tracker end if [: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 [:copy] # Manually update project_id on related time entries TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id}) end else Issue.connection.rollback_db_transaction return false end end return issue end |
- (Object) new_statuses_allowed_to(user)
Returns an array of status that user is able to apply
227 228 229 230 231 |
# File 'app/models/issue.rb', line 227 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 |
- (Boolean) overdue?
Returns true if the issue is overdue
217 218 219 |
# File 'app/models/issue.rb', line 217 def overdue? !due_date.nil? && (due_date < Date.today) && !status.is_closed? end |
- (Object) priority_id=(pid)
121 122 123 124 |
# File 'app/models/issue.rb', line 121 def priority_id=(pid) self.priority = nil write_attribute(:priority_id, pid) end |
- (Object) recipients
Returns the mail adresses of users that should be notified for the issue
234 235 236 237 238 239 240 |
# File 'app/models/issue.rb', line 234 def recipients recipients = project.recipients # Author and assignee are always notified unless they have been locked recipients << .mail if && .active? recipients << assigned_to.mail if assigned_to && assigned_to.active? recipients.compact.uniq end |
- (Object) relations
246 247 248 |
# File 'app/models/issue.rb', line 246 def relations (relations_from + relations_to).sort end |
- (Object) soonest_start
274 275 276 |
# File 'app/models/issue.rb', line 274 def soonest_start @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min end |
- (Object) spent_hours
242 243 244 |
# File 'app/models/issue.rb', line 242 def spent_hours @spent_hours ||= time_entries.sum(:hours) || 0 end |
- (Object) to_s
278 279 280 |
# File 'app/models/issue.rb', line 278 def to_s "#{tracker} ##{id}: #{subject}" end |
- (Object) validate
130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'app/models/issue.rb', line 130 def validate if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty? errors.add :due_date, :not_a_date end if self.due_date and self.start_date and self.due_date < self.start_date errors.add :due_date, :greater_than_start_date end if start_date && soonest_start && start_date < soonest_start errors.add :start_date, :invalid end end |
- (Object) validate_on_create
144 145 146 |
# File 'app/models/issue.rb', line 144 def validate_on_create errors.add :tracker_id, :invalid unless project.trackers.include?(tracker) end |
- (Boolean) visible?(usr = nil)
Returns true if usr or current user is allowed to view the issue
58 59 60 |
# File 'app/models/issue.rb', line 58 def visible?(usr=nil) (usr || User.current).allowed_to?(:view_issues, self.project) end |