Skip to content

Commit

Permalink
Merge pull request #11741 from opf/implementation/45081-journalize-pr…
Browse files Browse the repository at this point in the history
…oject-attributes-changes
  • Loading branch information
cbliard committed Dec 6, 2022
2 parents 1238638 + 2cc0a43 commit d318799
Show file tree
Hide file tree
Showing 13 changed files with 456 additions and 29 deletions.
7 changes: 5 additions & 2 deletions app/models/journal.rb
Expand Up @@ -56,6 +56,9 @@ class Journal < ApplicationRecord
# logs like the history on issue#show
scope :changing, -> { where(['version > 1']) }

scope :for_wiki_content, -> { where(journable_type: "WikiContent") }
scope :for_work_package, -> { where(journable_type: "WorkPackage") }

# In conjunction with the included Comparable module, allows comparison of journal records
# based on their corresponding version numbers, creation timestamps and IDs.
def <=>(other)
Expand Down Expand Up @@ -92,11 +95,11 @@ def details
end

def new_value_for(prop)
details[prop].last if details.keys.include? prop
details[prop].last if details.key? prop
end

def old_value_for(prop)
details[prop].first if details.keys.include? prop
details[prop].first if details.key? prop
end

def previous
Expand Down
31 changes: 31 additions & 0 deletions app/models/journal/project_journal.rb
@@ -0,0 +1,31 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 the OpenProject GmbH
#
# 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-2013 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 COPYRIGHT and LICENSE files for more details.
#++

class Journal::ProjectJournal < Journal::BaseJournal
self.table_name = 'project_journals'
end
2 changes: 2 additions & 0 deletions app/models/project.rb
Expand Up @@ -96,6 +96,8 @@ class Project < ApplicationRecord
project_key: 'id',
permission: nil

include Projects::Journalized

# Necessary for acts_as_searchable which depends on the event_datetime method for sorting
acts_as_event title: Proc.new { |o| "#{Project.model_name.human}: #{o.name}" },
url: Proc.new { |o| { controller: 'overviews/overviews', action: 'show', project_id: o } },
Expand Down
40 changes: 40 additions & 0 deletions app/models/projects/journalized.rb
@@ -0,0 +1,40 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2022 the OpenProject GmbH
#
# 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-2013 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 COPYRIGHT and LICENSE files for more details.
#++

module Projects::Journalized
extend ActiveSupport::Concern

included do
acts_as_journalized
end

# override acts_as_journalized method
def activity_type
'project_attributes'
end
end
15 changes: 15 additions & 0 deletions db/migrate/20221130150352_create_project_journals.rb
@@ -0,0 +1,15 @@
class CreateProjectJournals < ActiveRecord::Migration[7.0]
# rubocop:disable Rails/CreateTableWithTimestamps(RuboCop)
def change
create_table :project_journals do |t|
t.string :name, null: false
t.text :description
t.boolean :public, null: false
t.bigint :parent_id
t.string :identifier, null: false
t.boolean :active, null: false
t.boolean :templated, null: false
end
end
# rubocop:enable Rails/CreateTableWithTimestamps(RuboCop)
end
@@ -0,0 +1,16 @@
class AddNonNullConstraintOnProjectsIdentifier < ActiveRecord::Migration[7.0]
def change
reversible do |dir|
dir.up do
# should not be needed as all identifiers should be present
execute <<~SQL.squish
UPDATE projects
SET identifier = 'project-' || id
WHERE identifier IS NULL
SQL
end
end

change_column_null :projects, :identifier, false
end
end
@@ -0,0 +1,97 @@
class FillProjectJournalsWithExistingData < ActiveRecord::Migration[7.0]
def up
create_journal_entries_for_projects
end

def down
delete_journal_entries_for_projects
end

private

def create_journal_entries_for_projects
sql = <<~SQL.squish
WITH project_journals_insertion AS (
INSERT INTO project_journals(
name,
description,
public,
parent_id,
identifier,
active,
templated
)
SELECT name,
description,
public,
parent_id,
identifier,
active,
templated
FROM projects
RETURNING id,
identifier
),
journals_insertion AS (
INSERT into journals (
journable_id,
journable_type,
user_id,
created_at,
updated_at,
version,
data_type,
data_id
)
SELECT projects.id,
'Project',
:user_id,
projects.created_at,
projects.updated_at,
1,
'Journal::ProjectJournal',
project_journals_insertion.id
FROM projects
FULL JOIN project_journals_insertion ON projects.identifier = project_journals_insertion.identifier
RETURNING id,
journable_id
),
customizable_journals_insertion AS (
INSERT into customizable_journals (
journal_id,
custom_field_id,
value
)
SELECT journals_insertion.id,
custom_field_id,
value
FROM custom_values
FULL JOIN journals_insertion ON custom_values.customized_id = journals_insertion.journable_id
WHERE custom_values.customized_type = 'Project'
)
SELECT COUNT(1)
FROM journals_insertion;
SQL
sql = ::ActiveRecord::Base.sanitize_sql_array([sql, { user_id: User.system.id }])
execute(sql)
end

def delete_journal_entries_for_projects
execute(<<~SQL.squish)
DELETE
FROM customizable_journals
WHERE journal_id IN (
SELECT id FROM journals WHERE journable_type = 'Project'
)
SQL
execute(<<~SQL.squish)
DELETE
FROM journals
WHERE journable_type = 'Project'
SQL
execute(<<~SQL.squish)
DELETE
FROM project_journals
SQL
end
end
2 changes: 1 addition & 1 deletion spec/controllers/work_packages/bulk_controller_spec.rb
Expand Up @@ -324,7 +324,7 @@
it { expect(response.response_code).to eq(403) }

describe '#journal' do
subject { Journal.count }
subject { Journal.for_work_package.count }

it { is_expected.to eq(work_package_ids.count) }
end
Expand Down

0 comments on commit d318799

Please sign in to comment.