kanbanworkflowstimelinescrumrubyroadmapproject-planningproject-managementopenprojectangularissue-trackerifcgantt-chartganttbug-trackerboardsbcf
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
6.4 KiB
232 lines
6.4 KiB
#-- copyright
|
|
# OpenProject is a project management system.
|
|
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License version 3.
|
|
#
|
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
|
# Copyright (C) 2006-2017 Jean-Philippe Lang
|
|
# Copyright (C) 2010-2013 the ChiliProject Team
|
|
#
|
|
# 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.
|
|
#
|
|
# See doc/COPYRIGHT.rdoc for more details.
|
|
#++
|
|
|
|
class GenerateWpClosure < ActiveRecord::Migration[5.0]
|
|
def up
|
|
add_relation_type_column
|
|
|
|
update_relation_column_from_relation_type
|
|
|
|
invert_from_to_on_follows("relation_type = 'precedes'")
|
|
|
|
insert_hierarchy_relation_for_parent
|
|
|
|
remove_column :relations, :relation_type
|
|
|
|
remove_nested_set_columns
|
|
end
|
|
|
|
def down
|
|
recreate_nested_set_columns
|
|
|
|
invert_from_to_on_follows('follows = 1')
|
|
|
|
set_parent_id
|
|
|
|
remove_hierarchy_relations
|
|
|
|
fill_relation_type_column
|
|
|
|
remove_relation_type_specific_columns
|
|
|
|
rebuild_nested_set
|
|
end
|
|
|
|
def relation_types
|
|
%i(hierarchy relates duplicates blocks follows includes requires)
|
|
end
|
|
|
|
def add_relation_type_column
|
|
change_table :relations do |r|
|
|
relation_types.each do |column|
|
|
r.column column, :integer, default: 0, null: false
|
|
end
|
|
end
|
|
end
|
|
|
|
def remove_nested_set_columns
|
|
remove_column :work_packages, :parent_id
|
|
remove_column :work_packages, :root_id
|
|
remove_column :work_packages, :lft
|
|
remove_column :work_packages, :rgt
|
|
end
|
|
|
|
def recreate_nested_set_columns
|
|
add_column :work_packages, :parent_id, :integer
|
|
add_column :work_packages, :root_id, :integer
|
|
add_column :work_packages, :lft, :integer
|
|
add_column :work_packages, :rgt, :integer
|
|
|
|
add_index :work_packages, :parent_id
|
|
add_index :work_packages, %i(root_id lft rgt)
|
|
end
|
|
|
|
def remove_hierarchy_relations
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
DELETE FROM relations
|
|
WHERE hierarchy > 0
|
|
SQL
|
|
end
|
|
|
|
def invert_from_to_on_follows(condition)
|
|
if ActiveRecord::Base.connection.adapter_name == 'Mysql2'
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
UPDATE
|
|
relations r1,
|
|
relations r2
|
|
SET
|
|
r1.to_id = r1.from_id,
|
|
r1.from_id = r2.to_id
|
|
WHERE
|
|
r1.id = r2.id
|
|
AND
|
|
r1.#{condition}
|
|
SQL
|
|
else
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
UPDATE
|
|
relations
|
|
SET
|
|
from_id = to_id,
|
|
to_id = from_id
|
|
WHERE
|
|
#{condition}
|
|
SQL
|
|
end
|
|
end
|
|
|
|
def update_relation_column_from_relation_type
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
UPDATE
|
|
relations
|
|
SET
|
|
relates = CASE
|
|
WHEN relations.relation_type = 'relates'
|
|
THEN 1
|
|
ELSE 0
|
|
END,
|
|
duplicates = CASE
|
|
WHEN relations.relation_type = 'duplicates'
|
|
THEN 1
|
|
ELSE 0
|
|
END,
|
|
blocks = CASE
|
|
WHEN relations.relation_type = 'blocks'
|
|
THEN 1
|
|
ELSE 0
|
|
END,
|
|
follows = CASE
|
|
WHEN relations.relation_type = 'precedes'
|
|
THEN 1
|
|
ELSE 0
|
|
END,
|
|
includes = CASE
|
|
WHEN relations.relation_type = 'includes'
|
|
THEN 1
|
|
ELSE 0
|
|
END,
|
|
requires = CASE
|
|
WHEN relations.relation_type = 'requires'
|
|
THEN 1
|
|
ELSE 0
|
|
END
|
|
SQL
|
|
end
|
|
|
|
def insert_hierarchy_relation_for_parent
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
INSERT INTO relations
|
|
(from_id, to_id, hierarchy)
|
|
SELECT w1.id, w2.id, 1
|
|
FROM work_packages w1
|
|
JOIN work_packages w2
|
|
ON w1.id = w2.parent_id
|
|
SQL
|
|
end
|
|
|
|
def set_parent_id
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
UPDATE
|
|
work_packages
|
|
SET
|
|
parent_id =
|
|
(SELECT from_id
|
|
FROM relations
|
|
WHERE to_id = work_packages.id
|
|
AND relations.hierarchy = 1
|
|
AND relations.relates = 0
|
|
AND relations.duplicates = 0
|
|
AND relations.blocks = 0
|
|
AND relations.follows = 0
|
|
AND relations.includes = 0
|
|
AND relations.requires = 0)
|
|
SQL
|
|
end
|
|
|
|
def fill_relation_type_column
|
|
add_column :relations, :relation_type, :string
|
|
|
|
ActiveRecord::Base.connection.execute <<-SQL
|
|
UPDATE
|
|
relations
|
|
SET
|
|
relation_type = CASE
|
|
WHEN relations.relates = 1
|
|
THEN 'relates'
|
|
WHEN relations.duplicates = 1
|
|
THEN 'duplicates'
|
|
WHEN relations.duplicates = 1
|
|
THEN 'blocks'
|
|
WHEN relations.follows = 1
|
|
THEN 'precedes'
|
|
WHEN relations.includes = 1
|
|
THEN 'includes'
|
|
WHEN relations.requires = 1
|
|
THEN 'requires'
|
|
END
|
|
SQL
|
|
end
|
|
|
|
def remove_relation_type_specific_columns
|
|
relation_types.each do |column|
|
|
remove_column :relations, column
|
|
end
|
|
end
|
|
|
|
def rebuild_nested_set
|
|
NestedSetWorkPackage.rebuild_silently!
|
|
end
|
|
|
|
class NestedSetWorkPackage < ActiveRecord::Base
|
|
self.table_name = 'work_packages'
|
|
|
|
acts_as_nested_set scope: 'root_id', dependent: :destroy
|
|
|
|
include OpenProject::NestedSet::RebuildPatch
|
|
end
|
|
end
|
|
|