OpenProject is the leading open source project management software.
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.
 
 
 
 
 
 
openproject/db/migrate/20191216135213_join_table_f...

106 lines
3.3 KiB

class JoinTableForActiveActivities < ActiveRecord::Migration[6.0]
class ActivitiesJoinTable < ActiveRecord::Base
self.table_name = :time_entry_activities_projects
end
class TimeEntryActivity < ActiveRecord::Base
self.table_name = :enumerations
end
def up
create_join_table
delete_invalid_project_activities
link_time_entries_to_root_activities
fill_new_join_table
delete_inherited_activities
end
def down
create_project_specific_activities
link_time_entries_to_project_activities
drop_table :time_entry_activities_projects
end
def create_join_table
create_table :time_entry_activities_projects do |t|
t.references :activity, null: false, foreign_key: { to_table: :enumerations }, index: true
t.references :project, null: false, foreign_key: true, index: true
t.boolean :active, default: true, index: true
end
add_index :time_entry_activities_projects,
%i[project_id activity_id],
unique: true,
name: 'index_teap_on_project_id_and_activity_id'
end
# Delete all references from enumerations to projects which point to no longer
# existing projects.
def delete_invalid_project_activities
ActiveRecord::Base.connection.exec_query(
<<-SQL
DELETE FROM enumerations
USING enumerations AS enums
LEFT OUTER JOIN projects on enums.project_id = projects.id
WHERE enums.id = enumerations.id AND enums.type='TimeEntryActivity' AND projects.id IS NULL AND enums.project_id IS NOT NULL
SQL
)
end
def link_time_entries_to_root_activities
ActiveRecord::Base.connection.exec_query(
<<-SQL
UPDATE time_entries SET activity_id = enumerations.parent_id
FROM
time_entries te
INNER JOIN enumerations ON te.activity_id = enumerations.id AND enumerations.parent_id IS NOT NULL AND enumerations.type = 'TimeEntryActivity'
SQL
)
end
def link_time_entries_to_project_activities
ActiveRecord::Base.connection.exec_query(
<<-SQL
UPDATE time_entries SET activity_id = COALESCE(child.id, root.id)
FROM
time_entries te
INNER JOIN enumerations root ON te.activity_id = root.id AND root.type = 'TimeEntryActivity'
LEFT OUTER JOIN enumerations child ON child.parent_id = root.id
SQL
)
end
def fill_new_join_table
values = TimeEntryActivity
.where
.not(parent_id: nil)
.pluck(:project_id, :parent_id, :active)
.map { |project_id, parent_id, active| { project_id: project_id, activity_id: parent_id, active: active } }
ActivitiesJoinTable.insert_all(values) if values.present?
end
def delete_inherited_activities
TimeEntryActivity.where.not(parent_id: nil).delete_all
end
def create_project_specific_activities
ActiveRecord::Base.connection.exec_query(
<<-SQL
INSERT INTO enumerations (name, is_default, type, position, parent_id, project_id, active, created_at, updated_at)
SELECT
tea.name,
false,
tea.type,
tea.position,
teap.activity_id,
teap.project_id,
teap.active,
NOW(),
NOW()
FROM time_entry_activities_projects teap
JOIN enumerations tea ON tea.id = teap.activity_id AND tea.type = 'TimeEntryActivity'
SQL
)
end
end