From c732c42d7efa25a3645aec9d871d48cd7ee19e6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com>
Date: Fri, 28 Feb 2025 10:19:20 +0100
Subject: [PATCH] Migratable concern

---
 app/models/communication/block.rb             |  1 +
 .../communication/website/agenda/event.rb     |  1 +
 .../website/agenda/event/localization.rb      |  1 +
 app/models/communication/website/page.rb      |  1 +
 .../communication/website/page/category.rb    |  1 +
 .../website/page/category/localization.rb     |  1 +
 .../website/page/localization.rb              |  1 +
 .../website/portfolio/project.rb              |  1 +
 .../website/portfolio/project/localization.rb |  1 +
 app/models/communication/website/post.rb      |  1 +
 .../website/post/localization.rb              |  1 +
 app/models/concerns/migratable.rb             | 22 +++++++++++++++++++
 app/models/university/organization.rb         |  1 +
 .../university/organization/category.rb       |  1 +
 .../organization/category/localization.rb     |  1 +
 .../university/organization/localization.rb   |  1 +
 16 files changed, 37 insertions(+)
 create mode 100644 app/models/concerns/migratable.rb

diff --git a/app/models/communication/block.rb b/app/models/communication/block.rb
index 65337b013..2ffc550ad 100644
--- a/app/models/communication/block.rb
+++ b/app/models/communication/block.rb
@@ -38,6 +38,7 @@ class Communication::Block < ApplicationRecord
   }
 
   include AsIndirectObject
+  include Migratable
   include Orderable
   include WithAccessibility
   include WithHeadingRanks
diff --git a/app/models/communication/website/agenda/event.rb b/app/models/communication/website/agenda/event.rb
index e56492a8a..850a27fe9 100644
--- a/app/models/communication/website/agenda/event.rb
+++ b/app/models/communication/website/agenda/event.rb
@@ -38,6 +38,7 @@ class Communication::Website::Agenda::Event < ApplicationRecord
   include Sanitizable
   include Searchable
   include Localizable
+  include Migratable
   include WithMenuItemTarget
   include WithOpenApi
   include WithTime
diff --git a/app/models/communication/website/agenda/event/localization.rb b/app/models/communication/website/agenda/event/localization.rb
index f05740cd7..23e3fffa8 100644
--- a/app/models/communication/website/agenda/event/localization.rb
+++ b/app/models/communication/website/agenda/event/localization.rb
@@ -46,6 +46,7 @@ class Communication::Website::Agenda::Event::Localization < ApplicationRecord
   include Contentful
   include HeaderCallToAction
   include Initials
+  include Migratable
   include Permalinkable
   include Sanitizable
   include Shareable
diff --git a/app/models/communication/website/page.rb b/app/models/communication/website/page.rb
index 5778cbeb8..6116fea91 100644
--- a/app/models/communication/website/page.rb
+++ b/app/models/communication/website/page.rb
@@ -37,6 +37,7 @@ class Communication::Website::Page < ApplicationRecord
   include Filterable
   include Categorizable # Must be loaded after Filterable to be filtered by categories
   include Localizable
+  include Migratable
   include Orderable
   include Sanitizable
   include Searchable
diff --git a/app/models/communication/website/page/category.rb b/app/models/communication/website/page/category.rb
index 8f82f6235..483f37677 100644
--- a/app/models/communication/website/page/category.rb
+++ b/app/models/communication/website/page/category.rb
@@ -34,6 +34,7 @@ class Communication::Website::Page::Category < ApplicationRecord
   include AsDirectObject
   include Sanitizable
   include Localizable
+  include Migratable
   include WithMenuItemTarget
   include WithOpenApi
   include WithUniversity
diff --git a/app/models/communication/website/page/category/localization.rb b/app/models/communication/website/page/category/localization.rb
index 545b225d6..b5df33859 100644
--- a/app/models/communication/website/page/category/localization.rb
+++ b/app/models/communication/website/page/category/localization.rb
@@ -34,6 +34,7 @@
 #
 class Communication::Website::Page::Category::Localization < ApplicationRecord
   include AsCategoryLocalization
+  include Migratable
   include WithOpenApi
 
   belongs_to :website,
diff --git a/app/models/communication/website/page/localization.rb b/app/models/communication/website/page/localization.rb
index 8ff5c3012..a7d01cac9 100644
--- a/app/models/communication/website/page/localization.rb
+++ b/app/models/communication/website/page/localization.rb
@@ -45,6 +45,7 @@ class Communication::Website::Page::Localization < ApplicationRecord
   include Contentful
   include HeaderCallToAction
   include Initials
+  include Migratable
   include Permalinkable
   include Sanitizable
   include Shareable
diff --git a/app/models/communication/website/portfolio/project.rb b/app/models/communication/website/portfolio/project.rb
index 88db739cc..611aaacf6 100644
--- a/app/models/communication/website/portfolio/project.rb
+++ b/app/models/communication/website/portfolio/project.rb
@@ -32,6 +32,7 @@ class Communication::Website::Portfolio::Project < ApplicationRecord
   include Sanitizable
   include Searchable
   include Localizable
+  include Migratable
   include WithMenuItemTarget
   include WithUniversity
 
diff --git a/app/models/communication/website/portfolio/project/localization.rb b/app/models/communication/website/portfolio/project/localization.rb
index 2283ad1bb..0d5b17a99 100644
--- a/app/models/communication/website/portfolio/project/localization.rb
+++ b/app/models/communication/website/portfolio/project/localization.rb
@@ -42,6 +42,7 @@ class Communication::Website::Portfolio::Project::Localization < ApplicationReco
   include Contentful
   include HeaderCallToAction
   include Initials
+  include Migratable
   include Permalinkable
   include Sanitizable
   include Shareable
diff --git a/app/models/communication/website/post.rb b/app/models/communication/website/post.rb
index d915b1a3e..e0f99c0db 100644
--- a/app/models/communication/website/post.rb
+++ b/app/models/communication/website/post.rb
@@ -28,6 +28,7 @@ class Communication::Website::Post < ApplicationRecord
   include Sanitizable
   include Searchable
   include Localizable
+  include Migratable
   include WithMenuItemTarget
   include WithOpenApi
   include WithUniversity
diff --git a/app/models/communication/website/post/localization.rb b/app/models/communication/website/post/localization.rb
index d47b764a8..a80dad48b 100644
--- a/app/models/communication/website/post/localization.rb
+++ b/app/models/communication/website/post/localization.rb
@@ -44,6 +44,7 @@ class Communication::Website::Post::Localization < ApplicationRecord
   include Contentful
   include HeaderCallToAction
   include Initials
+  include Migratable
   include Permalinkable
   include Sanitizable
   include Shareable
diff --git a/app/models/concerns/migratable.rb b/app/models/concerns/migratable.rb
new file mode 100644
index 000000000..b5338f5ad
--- /dev/null
+++ b/app/models/concerns/migratable.rb
@@ -0,0 +1,22 @@
+module Migratable
+  extend ActiveSupport::Concern
+
+  included do
+    validate :migration_identifier_must_be_unique, if: -> { migration_identifier.present? }
+  end
+
+  protected
+
+  def migration_identifier_unavailable?
+    existence_params = { migration_identifier: migration_identifier }
+    existence_params[:university_id] = self.university_id if respond_to?(:university_id)
+    self.class.unscoped
+              .where(**existence_params)
+              .where.not(id: self.id)
+              .exists?
+  end
+
+  def migration_identifier_must_be_unique
+    errors.add(:migration_identifier, :taken) if migration_identifier_unavailable?
+  end
+end
\ No newline at end of file
diff --git a/app/models/university/organization.rb b/app/models/university/organization.rb
index afa5fb6d9..9de8b4d9e 100644
--- a/app/models/university/organization.rb
+++ b/app/models/university/organization.rb
@@ -34,6 +34,7 @@ class University::Organization < ApplicationRecord
   include Categorizable # Must be loaded after Filterable to be filtered by categories
   include Localizable
   include LocalizableOrderByNameScope
+  include Migratable
   include Sanitizable
   include Searchable
   include WithCountry
diff --git a/app/models/university/organization/category.rb b/app/models/university/organization/category.rb
index f8f3919cd..bc571ad3f 100644
--- a/app/models/university/organization/category.rb
+++ b/app/models/university/organization/category.rb
@@ -26,6 +26,7 @@ class University::Organization::Category < ApplicationRecord
   include AsCategory
   include AsIndirectObject
   include Localizable
+  include Migratable
   include WithOpenApi
   include WithUniversity
 
diff --git a/app/models/university/organization/category/localization.rb b/app/models/university/organization/category/localization.rb
index fb79e4d43..1b3040683 100644
--- a/app/models/university/organization/category/localization.rb
+++ b/app/models/university/organization/category/localization.rb
@@ -31,6 +31,7 @@
 #
 class University::Organization::Category::Localization < ApplicationRecord
   include AsCategoryLocalization
+  include Migratable
   include WithOpenApi
 
   def git_path(website)
diff --git a/app/models/university/organization/localization.rb b/app/models/university/organization/localization.rb
index e5f884f79..522099612 100644
--- a/app/models/university/organization/localization.rb
+++ b/app/models/university/organization/localization.rb
@@ -41,6 +41,7 @@ class University::Organization::Localization < ApplicationRecord
   include Backlinkable
   include Contentful
   include Initials
+  include Migratable
   include Permalinkable
   include Sanitizable
   include Shareable
-- 
GitLab