Move relations to work package

pull/243/head
Hagen Schink 11 years ago committed by Jens Ulferts
parent cc54e7722c
commit 89544eb63f
  1. 87
      app/models/issue.rb
  2. 4
      app/models/issue_relation.rb
  3. 88
      app/models/work_package.rb

@ -18,9 +18,6 @@ class Issue < WorkPackage
has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC"
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
DONE_RATIO_OPTIONS = %w(issue_field issue_status)
ATTRIBS_WITH_VALUES_FROM_CHILDREN = %w(priority_id start_date due_date estimated_hours done_ratio)
@ -124,11 +121,7 @@ class Issue < WorkPackage
issue = options[:copy] ? self.class.new.copy_from(self) : self
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
delete_relations(issue)
# 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)
@ -361,11 +354,6 @@ class Issue < WorkPackage
end
end
# Return true if the issue is closed, otherwise false
def closed?
self.status.is_closed?
end
# Return true if the issue is being reopened
def reopened?
if !new_record? && status_id_changed?
@ -419,11 +407,6 @@ class Issue < WorkPackage
@assignable_versions ||= (project.shared_versions.open + [Version.find_by_id(fixed_version_id_was)]).compact.uniq.sort
end
# Returns true if this issue is blocked by another issue that is still open
def blocked?
!relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
end
# Returns an array of status that user is able to apply
def new_statuses_allowed_to(user, include_default=false)
statuses = status.find_new_statuses_allowed_to(
@ -460,51 +443,6 @@ class Issue < WorkPackage
@spent_hours ||= self_and_descendants.joins(:time_entries).sum("#{TimeEntry.table_name}.hours").to_f || 0.0
end
def relations(options = {})
options_to = options.clone
options_from = options.clone
if options[:include]
if options[:include].is_a?(Hash) && options[:include][:other_issue]
options_to[:include] = options_to[:include].dup
options_from[:include] = options_from[:include].dup
options_to[:include][:issue_from] = options_to[:include].delete(:other_issue)
options_from[:include][:issue_to] = options_from[:include].delete(:other_issue)
elsif options[:include].is_a?(Array) && options[:include].include?(:other_issue)
options_to[:include] = options[:include].dup - [:other_issue] + [:issue_from]
options_from[:include] = options[:include].dup - [:other_issue] + [:issue_to]
end
end
(relations_from.all(options_from) + relations_to.all(options_to)).sort
end
def relation(id)
IssueRelation.of_issue(self).find(id)
end
def new_relation
self.relations_from.build
end
def all_dependent_issues(except=[])
except << self
dependencies = []
relations_from.each do |relation|
if relation.issue_to && !except.include?(relation.issue_to)
dependencies << relation.issue_to
dependencies += relation.issue_to.all_dependent_issues(except)
end
end
dependencies
end
# Returns an array of issues that duplicate this one
def duplicates
relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from}
end
# Returns the time scheduled for this issue.
#
# Example:
@ -514,13 +452,6 @@ class Issue < WorkPackage
(start_date && due_date) ? due_date - start_date : 0
end
def soonest_start
@soonest_start ||= (
relations_to.collect{|relation| relation.successor_soonest_start} +
ancestors.collect(&:soonest_start)
).compact.max
end
def reschedule_after(date)
return if date.nil?
if leaf?
@ -808,12 +739,7 @@ class Issue < WorkPackage
end
end
reload
# delete invalid relations of all descendants
self_and_descendants.each do |issue|
issue.relations.each do |relation|
relation.destroy unless relation.valid?
end
end
# update former parent
recalculate_attributes_for(former_parent_id) if former_parent_id
end
@ -901,15 +827,6 @@ class Issue < WorkPackage
end
end
# Updates start/due dates of following issues
def reschedule_following_issues
if start_date_changed? || due_date_changed?
relations_from.each do |relation|
relation.set_issue_to_dates
end
end
end
# Closes duplicates if the issue is being closed
def close_duplicates
if closing?

@ -11,8 +11,8 @@
#++
class IssueRelation < ActiveRecord::Base
belongs_to :issue_from, :class_name => 'Issue', :foreign_key => 'issue_from_id'
belongs_to :issue_to, :class_name => 'Issue', :foreign_key => 'issue_to_id'
belongs_to :issue_from, :class_name => 'WorkPackage', :foreign_key => 'issue_from_id'
belongs_to :issue_to, :class_name => 'WorkPackage', :foreign_key => 'issue_to_id'
scope :of_issue, ->(issue) { where('issue_from_id = ? OR issue_to_id = ?', issue, issue) }

@ -33,6 +33,8 @@ class WorkPackage < ActiveRecord::Base
:foreign_key => 'planning_element_status_id'
has_many :time_entries, :dependent => :delete_all
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
scope :recently_updated, :order => "#{WorkPackage.table_name}.updated_at DESC"
scope :visible, lambda {|*args| { :include => :project,
@ -139,6 +141,87 @@ class WorkPackage < ActiveRecord::Base
"work_packages"
end
# RELATIONS
def delete_relations(work_package)
unless Setting.cross_project_issue_relations?
work_package.relations_from.clear
work_package.relations_to.clear
end
end
def delete_invalid_relations(invalid_work_packages)
invalid_work_package.each do |work_package|
work_package.relations.each do |relation|
relation.destroy unless relation.valid?
end
end
end
# Returns true if this work package is blocked by another work package that is still open
def blocked?
!relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
end
def relations(options = {})
options_to = options.clone
options_from = options.clone
if options[:include]
if options[:include].is_a?(Hash) && options[:include][:other_issue]
options_to[:include] = options_to[:include].dup
options_from[:include] = options_from[:include].dup
options_to[:include][:issue_from] = options_to[:include].delete(:other_issue)
options_from[:include][:issue_to] = options_from[:include].delete(:other_issue)
elsif options[:include].is_a?(Array) && options[:include].include?(:other_issue)
options_to[:include] = options[:include].dup - [:other_issue] + [:issue_from]
options_from[:include] = options[:include].dup - [:other_issue] + [:issue_to]
end
end
(relations_from.all(options_from) + relations_to.all(options_to)).sort
end
def relation(id)
IssueRelation.of_issue(self).find(id)
end
def new_relation
self.relations_from.build
end
def all_dependent_issues(except=[])
except << self
dependencies = []
relations_from.each do |relation|
if relation.issue_to && !except.include?(relation.issue_to)
dependencies << relation.issue_to
dependencies += relation.issue_to.all_dependent_issues(except)
end
end
dependencies
end
# Returns an array of issues that duplicate this one
def duplicates
relations_to.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.issue_from}
end
def soonest_start
@soonest_start ||= (
relations_to.collect{|relation| relation.successor_soonest_start} +
ancestors.collect(&:soonest_start)
).compact.max
end
# Updates start/due dates of following issues
def reschedule_following_issues
if start_date_changed? || due_date_changed?
relations_from.each do |relation|
relation.set_issue_to_dates
end
end
end
def kind
if self.is_a? Issue
return tracker
@ -150,4 +233,9 @@ class WorkPackage < ActiveRecord::Base
def to_s
"#{(kind.nil?) ? '' : kind.name} ##{id}: #{subject}"
end
# Return true if the work_package is closed, otherwise false
def closed?
self.status.nil? || self.status.is_closed?
end
end

Loading…
Cancel
Save