From f38bd2a3ceefa6f33484b8b17fdb25bd52e810c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= Date: Mon, 19 Oct 2026 11:24:37 +0200 Subject: [PATCH 1/2] Move to future GoodJob v5 concurrency rules --- app/jobs/application_job.rb | 75 +- .../website/git_file/generate_content_job.rb | 14 +- app/models/communication/block.rb | 2 +- app/models/communication/extranet.rb | 2 +- app/models/communication/media.rb | 2 +- app/models/communication/website.rb | 4 +- app/models/communication/website/alert.rb | 2 +- app/models/communication/website/menu/item.rb | 2 +- app/models/education/diploma.rb | 2 +- app/models/import.rb | 2 +- app/models/research/publication.rb | 2 +- app/models/university.rb | 4 +- app/models/university/organization.rb | 2 +- app/models/university/person.rb | 16 +- app/models/university/person/alumnus.rb | 16 +- app/models/user.rb | 2 +- ...ex_good_jobs_concurrency_key_created_at.rb | 17 + ...019092220_add_index_good_jobs_job_class.rb | 17 + ...index_good_jobs_finished_at_for_cleanup.rb | 17 + ...222_remove_extraneous_finished_at_index.rb | 17 + ...261019092223_add_lock_type_to_good_jobs.rb | 7 + ...ood_jobs_for_candidate_dequeue_unlocked.rb | 14 + ...d_index_good_jobs_priority_scheduled_at.rb | 23 + ...19092226_add_index_good_jobs_queue_name.rb | 12 + ...19092227_add_index_good_jobs_created_at.rb | 12 + ...019092228_add_index_good_jobs_discarded.rb | 14 + ...x_good_jobs_scheduled_at_and_queue_name.rb | 12 + ...ndex_good_jobs_on_unfinished_or_errored.rb | 13 + ...add_index_good_jobs_discarded_job_class.rb | 13 + ...32_add_index_good_jobs_dequeue_by_queue.rb | 21 + ...dex_good_job_executions_on_scheduled_at.rb | 12 + .../20261019092234_add_batch_query_indexes.rb | 28 + ...2235_remove_redundant_good_jobs_indexes.rb | 55 + ...1019092236_reorder_good_jobs_cron_index.rb | 51 + ...2237_create_good_job_concurrency_claims.rb | 27 + db/schema.rb | 2041 +++++++++-------- 36 files changed, 1486 insertions(+), 1086 deletions(-) create mode 100644 db/migrate/20261019092219_add_index_good_jobs_concurrency_key_created_at.rb create mode 100644 db/migrate/20261019092220_add_index_good_jobs_job_class.rb create mode 100644 db/migrate/20261019092221_add_index_good_jobs_finished_at_for_cleanup.rb create mode 100644 db/migrate/20261019092222_remove_extraneous_finished_at_index.rb create mode 100644 db/migrate/20261019092223_add_lock_type_to_good_jobs.rb create mode 100644 db/migrate/20261019092224_add_index_good_jobs_for_candidate_dequeue_unlocked.rb create mode 100644 db/migrate/20261019092225_add_index_good_jobs_priority_scheduled_at.rb create mode 100644 db/migrate/20261019092226_add_index_good_jobs_queue_name.rb create mode 100644 db/migrate/20261019092227_add_index_good_jobs_created_at.rb create mode 100644 db/migrate/20261019092228_add_index_good_jobs_discarded.rb create mode 100644 db/migrate/20261019092229_add_index_good_jobs_scheduled_at_and_queue_name.rb create mode 100644 db/migrate/20261019092230_add_index_good_jobs_on_unfinished_or_errored.rb create mode 100644 db/migrate/20261019092231_add_index_good_jobs_discarded_job_class.rb create mode 100644 db/migrate/20261019092232_add_index_good_jobs_dequeue_by_queue.rb create mode 100644 db/migrate/20261019092233_add_index_good_job_executions_on_scheduled_at.rb create mode 100644 db/migrate/20261019092234_add_batch_query_indexes.rb create mode 100644 db/migrate/20261019092235_remove_redundant_good_jobs_indexes.rb create mode 100644 db/migrate/20261019092236_reorder_good_jobs_cron_index.rb create mode 100644 db/migrate/20261019092237_create_good_job_concurrency_claims.rb diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index dbf4fb289e..849adca682 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -8,59 +8,54 @@ class ApplicationJob < ActiveJob::Base include GoodJob::ActiveJobExtensions::Concurrency - before_enqueue :add_good_job_labels - - good_job_control_concurrency_with( - # Maximum number of unfinished jobs to allow with the concurrency key - # Can be an Integer or Lambda/Proc that is invoked in the context of the job - # total_limit: 1, + # Define one or more concurrency rules. Each rule is scoped to a label, + # which is a value derived from the job's arguments at enqueue time and + # stored on the job record. Jobs must be enqueued with the matching label + # via `good_job_labels:` for the rule to apply. + # + # Multiple rules can be defined; they are evaluated in order and the first + # exceeded rule short-circuits the rest. + good_job_concurrency_rule( + # A label that scopes this rule. Can be a static String or a Lambda/Proc + # invoked in the context of the job instance (see "Dynamic labels" below). + # The rule only applies to jobs that were enqueued with this label in + # `good_job_labels`. + label: -> { "#{self.class.name}-#{queue_name}-#{digest_arguments(arguments)}" } + + # Apply the rule's label to every job of this class (and its subclasses), + # so the jobs don't need to be enqueued with it. Defaults to false. + # A Lambda/Proc label that returns nil is not applied. + apply_label: true, + + # Maximum number of unfinished jobs with this label to allow. + # Can be an Integer or Lambda/Proc invoked in the context of the job. + total_limit: 1, # Or, if more control is needed: - # Maximum number of jobs with the concurrency key to be - # concurrently enqueued (excludes performing jobs) - # Can be an Integer or Lambda/Proc that is invoked in the context of the job + # Maximum number of jobs with this label to be concurrently enqueued + # (excludes performing jobs). Can be an Integer or Lambda/Proc. enqueue_limit: 1, - # Maximum number of jobs with the concurrency key to be - # concurrently performed (excludes enqueued jobs) - # Can be an Integer or Lambda/Proc that is invoked in the context of the job + # Maximum number of jobs with this label to be concurrently performed + # (excludes enqueued jobs). Can be an Integer or Lambda/Proc. perform_limit: 1, - # Maximum number of jobs with the concurrency key to be enqueued within - # the time period, looking backwards from the current time. Must be an array - # with two elements: the number of jobs and the time period. + # Maximum number of jobs with this label to be enqueued within the time + # period, looking backwards from now. Must be [count, period]. enqueue_throttle: [10, 1.minute], - # Maximum number of jobs with the concurrency key to be performed within - # the time period, looking backwards from the current time. Must be an array - # with two elements: the number of jobs and the time period. + # Maximum number of jobs with this label to be performed within the time + # period, looking backwards from now. Must be [count, period]. perform_throttle: [100, 1.hour], # Note: Under heavy load, the total number of jobs may exceed the # sum of `enqueue_limit` and `perform_limit` because of race conditions # caused by imperfectly disjunctive states. If you need to constrain # the total number of jobs, use `total_limit` instead. See #378. - - # A unique key to be globally locked against. - # Can be String or Lambda/Proc that is invoked in the context of the job. - # - # If a key is not provided GoodJob will use the job class name. - # - # To disable concurrency control, for example in a subclass, set the - # key explicitly to nil (e.g. `key: nil` or `key: -> { nil }`) - # - # If you provide a custom concurrency key (for example, if concurrency is supposed - # to be controlled by the first job argument) make sure that it is sufficiently unique across - # jobs and queues by adding the job class or queue to the key yourself, if needed. - # - # Note: When using a model instance as part of your custom concurrency key, make sure - # to explicitly use its `id` or `to_global_id` because otherwise it will not stringify as expected. - # - # Note: Arguments passed to #perform_later can be accessed through Active Job's `arguments` method - # which is an array containing positional arguments and, optionally, a kwarg hash. - key: -> { "#{self.class.name}-#{queue_name}-#{digest_arguments(arguments)}" } ) + before_enqueue :add_good_job_labels + protected def good_job_additional_labels @@ -71,11 +66,7 @@ def good_job_additional_labels def add_good_job_labels return if good_job_additional_labels.empty? - if @good_job_labels.nil? - @good_job_labels = good_job_additional_labels - else - @good_job_labels += good_job_additional_labels - end + self.good_job_labels |= good_job_additional_labels end def digest_arguments(arguments) diff --git a/app/jobs/communication/website/git_file/generate_content_job.rb b/app/jobs/communication/website/git_file/generate_content_job.rb index 0d6c5fc5e8..d590b4c7ce 100644 --- a/app/jobs/communication/website/git_file/generate_content_job.rb +++ b/app/jobs/communication/website/git_file/generate_content_job.rb @@ -1,14 +1,14 @@ class Communication::Website::GitFile::GenerateContentJob < ApplicationJob queue_as :cats - def perform(git_file) - git_file.generate_content_safely - end - - good_job_control_concurrency_with( + good_job_concurrency_rule( enqueue_limit: 1, perform_limit: 1, - key: -> { "#{self.class.name}-#{queue_name}-#{arguments.first.to_global_id}" } + label: -> { "#{self.class.name}-#{queue_name}-#{arguments.first.to_global_id}" } ) -end \ No newline at end of file + def perform(git_file) + git_file.generate_content_safely + end + +end diff --git a/app/models/communication/block.rb b/app/models/communication/block.rb index f56e46405c..714da6fc1d 100644 --- a/app/models/communication/block.rb +++ b/app/models/communication/block.rb @@ -11,7 +11,7 @@ # migration_identifier :string # position :integer not null # published :boolean default(TRUE) -# template_kind :integer default(0), not null, indexed => [university_id] +# template_kind :integer default(NULL), not null, indexed => [university_id] # title :string # created_at :datetime not null # updated_at :datetime not null diff --git a/app/models/communication/extranet.rb b/app/models/communication/extranet.rb index fa3400a78b..b290da2bd3 100644 --- a/app/models/communication/extranet.rb +++ b/app/models/communication/extranet.rb @@ -17,7 +17,7 @@ # sso_cert :text # sso_mapping :jsonb # sso_name_identifier_format :string -# sso_provider :integer default(0) +# sso_provider :integer default("saml") # sso_target_url :string # upper_menu :text default("") # created_at :datetime not null diff --git a/app/models/communication/media.rb b/app/models/communication/media.rb index 12ebc71178..cb740fc629 100644 --- a/app/models/communication/media.rb +++ b/app/models/communication/media.rb @@ -4,7 +4,7 @@ # # id :uuid not null, primary key # deleted_at :datetime indexed -# origin :integer default(1), not null +# origin :integer default("upload"), not null # original_byte_size :bigint # original_checksum :string # original_content_type :string diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb index 4217d8a6c6..517388a5f8 100644 --- a/app/models/communication/website.rb +++ b/app/models/communication/website.rb @@ -24,9 +24,9 @@ # git_branch :string # git_endpoint :string # git_files_analysed_at :datetime -# git_provider :integer default(0) +# git_provider :integer default("github") # highlighted_in_showcase :boolean default(FALSE) -# hosting :integer default(1), not null +# hosting :integer default("deuxfleurs"), not null # in_production :boolean default(FALSE) # in_production_at :datetime # in_showcase :boolean default(TRUE) diff --git a/app/models/communication/website/alert.rb b/app/models/communication/website/alert.rb index ce01fd4aa8..d484925d25 100644 --- a/app/models/communication/website/alert.rb +++ b/app/models/communication/website/alert.rb @@ -4,7 +4,7 @@ # # id :uuid not null, primary key # deleted_at :datetime -# kind :integer default(0), not null +# kind :integer default("info"), not null # created_at :datetime not null # updated_at :datetime not null # communication_website_id :uuid not null, indexed diff --git a/app/models/communication/website/menu/item.rb b/app/models/communication/website/menu/item.rb index f2dd1b7a62..92b426c86f 100644 --- a/app/models/communication/website/menu/item.rb +++ b/app/models/communication/website/menu/item.rb @@ -5,7 +5,7 @@ # id :uuid not null, primary key # about_type :string indexed => [about_id] # html_class :string -# kind :integer default(0) +# kind :integer default("blank") # position :integer not null # position_in_tree :integer # should_open_new_tab :boolean default(FALSE) diff --git a/app/models/education/diploma.rb b/app/models/education/diploma.rb index 3ccbccff34..40eda6a697 100644 --- a/app/models/education/diploma.rb +++ b/app/models/education/diploma.rb @@ -6,7 +6,7 @@ # certification :string # deleted_at :datetime # ects :integer -# level :integer default(0) +# level :integer default("not_applicable") # position :integer not null # created_at :datetime not null # updated_at :datetime not null diff --git a/app/models/import.rb b/app/models/import.rb index 5e8c040f9f..c4f08546c2 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -6,7 +6,7 @@ # kind :integer # number_of_lines :integer # processing_errors :jsonb -# status :integer default(0) +# status :integer default("pending") # created_at :datetime not null # updated_at :datetime not null # language_id :uuid not null, indexed diff --git a/app/models/research/publication.rb b/app/models/research/publication.rb index 11efe7a644..d5f4aca37f 100644 --- a/app/models/research/publication.rb +++ b/app/models/research/publication.rb @@ -20,7 +20,7 @@ # publication_date :date # ref :string # slug :string indexed -# source :integer default(0) +# source :integer default("osuny") # title :string # url :string # created_at :datetime not null diff --git a/app/models/university.rb b/app/models/university.rb index 8fc86a2616..403105a80c 100644 --- a/app/models/university.rb +++ b/app/models/university.rb @@ -22,7 +22,7 @@ # sso_cert :text # sso_mapping :jsonb # sso_name_identifier_format :string -# sso_provider :integer default(0) +# sso_provider :integer default("saml") # sso_target_url :string # zipcode :string # created_at :datetime not null @@ -32,7 +32,7 @@ # Indexes # # index_universities_on_default_language_id (default_language_id) -# index_universities_on_name (name) USING gin +# index_universities_on_name (name gin_trgm_ops) USING gin # # Foreign Keys # diff --git a/app/models/university/organization.rb b/app/models/university/organization.rb index 9dd6da41f4..e1c53c36f1 100644 --- a/app/models/university/organization.rb +++ b/app/models/university/organization.rb @@ -9,7 +9,7 @@ # country :string # deleted_at :datetime # email :string -# kind :integer default(10) +# kind :integer default("company") # latitude :float # longitude :float # migration_identifier :string diff --git a/app/models/university/person.rb b/app/models/university/person.rb index 44849aab88..ecb561eed4 100644 --- a/app/models/university/person.rb +++ b/app/models/university/person.rb @@ -4,14 +4,14 @@ # # id :uuid not null, primary key # address :string -# address_visibility :integer default(0) +# address_visibility :integer default("private") # birthdate :date # bodyclass :string # city :string # country :string # deleted_at :datetime # email :string -# email_visibility :integer default(0) +# email_visibility :integer default("private") # gender :integer # habilitation :boolean default(FALSE) # invitation_sent_at :datetime @@ -20,16 +20,16 @@ # is_author :boolean # is_researcher :boolean # is_teacher :boolean -# linkedin_visibility :integer default(0) -# mastodon_visibility :integer default(0) +# linkedin_visibility :integer default("private") +# mastodon_visibility :integer default("private") # phone_mobile :string -# phone_mobile_visibility :integer default(0) +# phone_mobile_visibility :integer default("private") # phone_personal :string -# phone_personal_visibility :integer default(0) +# phone_personal_visibility :integer default("private") # phone_professional :string -# phone_professional_visibility :integer default(0) +# phone_professional_visibility :integer default("private") # tenure :boolean default(FALSE) -# twitter_visibility :integer default(0) +# twitter_visibility :integer default("private") # zipcode :string # created_at :datetime not null # updated_at :datetime not null diff --git a/app/models/university/person/alumnus.rb b/app/models/university/person/alumnus.rb index ecd01470c1..59a83846dd 100644 --- a/app/models/university/person/alumnus.rb +++ b/app/models/university/person/alumnus.rb @@ -4,14 +4,14 @@ # # id :uuid not null, primary key # address :string -# address_visibility :integer default(0) +# address_visibility :integer default("private") # birthdate :date # bodyclass :string # city :string # country :string # deleted_at :datetime # email :string -# email_visibility :integer default(0) +# email_visibility :integer default("private") # gender :integer # habilitation :boolean default(FALSE) # invitation_sent_at :datetime @@ -20,16 +20,16 @@ # is_author :boolean # is_researcher :boolean # is_teacher :boolean -# linkedin_visibility :integer default(0) -# mastodon_visibility :integer default(0) +# linkedin_visibility :integer default("private") +# mastodon_visibility :integer default("private") # phone_mobile :string -# phone_mobile_visibility :integer default(0) +# phone_mobile_visibility :integer default("private") # phone_personal :string -# phone_personal_visibility :integer default(0) +# phone_personal_visibility :integer default("private") # phone_professional :string -# phone_professional_visibility :integer default(0) +# phone_professional_visibility :integer default("private") # tenure :boolean default(FALSE) -# twitter_visibility :integer default(0) +# twitter_visibility :integer default("private") # zipcode :string # created_at :datetime not null # updated_at :datetime not null diff --git a/app/models/user.rb b/app/models/user.rb index 0ca5f08f9f..595715c38a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -28,7 +28,7 @@ # remember_created_at :datetime # reset_password_sent_at :datetime # reset_password_token :string uniquely indexed -# role :integer default(0) +# role :integer default("visitor") # second_factor_attempts_count :integer default(0) # session_token :string # sign_in_count :integer default(0), not null diff --git a/db/migrate/20261019092219_add_index_good_jobs_concurrency_key_created_at.rb b/db/migrate/20261019092219_add_index_good_jobs_concurrency_key_created_at.rb new file mode 100644 index 0000000000..b51825d60e --- /dev/null +++ b/db/migrate/20261019092219_add_index_good_jobs_concurrency_key_created_at.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsConcurrencyKeyCreatedAt < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_exists? :good_jobs, [:concurrency_key, :created_at] + end + end + + add_index :good_jobs, [:concurrency_key, :created_at], algorithm: :concurrently + end +end diff --git a/db/migrate/20261019092220_add_index_good_jobs_job_class.rb b/db/migrate/20261019092220_add_index_good_jobs_job_class.rb new file mode 100644 index 0000000000..f55ac86658 --- /dev/null +++ b/db/migrate/20261019092220_add_index_good_jobs_job_class.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsJobClass < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_exists? :good_jobs, :job_class + end + end + + add_index :good_jobs, :job_class, algorithm: :concurrently + end +end \ No newline at end of file diff --git a/db/migrate/20261019092221_add_index_good_jobs_finished_at_for_cleanup.rb b/db/migrate/20261019092221_add_index_good_jobs_finished_at_for_cleanup.rb new file mode 100644 index 0000000000..6a8032a91d --- /dev/null +++ b/db/migrate/20261019092221_add_index_good_jobs_finished_at_for_cleanup.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsFinishedAtForCleanup < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_exists? :good_jobs, [:finished_at], name: :index_good_jobs_jobs_on_finished_at_only + end + end + + add_index :good_jobs, [:finished_at], where: "finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at_only, algorithm: :concurrently + end +end diff --git a/db/migrate/20261019092222_remove_extraneous_finished_at_index.rb b/db/migrate/20261019092222_remove_extraneous_finished_at_index.rb new file mode 100644 index 0000000000..1a19158bf5 --- /dev/null +++ b/db/migrate/20261019092222_remove_extraneous_finished_at_index.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class RemoveExtraneousFinishedAtIndex < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return unless connection.index_exists? :good_jobs, [:finished_at], name: :index_good_jobs_jobs_on_finished_at + end + end + + remove_index :good_jobs, [:finished_at], where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at, algorithm: :concurrently + end +end diff --git a/db/migrate/20261019092223_add_lock_type_to_good_jobs.rb b/db/migrate/20261019092223_add_lock_type_to_good_jobs.rb new file mode 100644 index 0000000000..048742008d --- /dev/null +++ b/db/migrate/20261019092223_add_lock_type_to_good_jobs.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddLockTypeToGoodJobs < ActiveRecord::Migration[8.1] + def change + add_column :good_jobs, :lock_type, :integer, limit: 2 unless column_exists?(:good_jobs, :lock_type) + end +end diff --git a/db/migrate/20261019092224_add_index_good_jobs_for_candidate_dequeue_unlocked.rb b/db/migrate/20261019092224_add_index_good_jobs_for_candidate_dequeue_unlocked.rb new file mode 100644 index 0000000000..aeb72c0320 --- /dev/null +++ b/db/migrate/20261019092224_add_index_good_jobs_for_candidate_dequeue_unlocked.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsForCandidateDequeueUnlocked < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, [:priority, :scheduled_at, :id], + name: :index_good_jobs_for_candidate_dequeue_unlocked, + order: { priority: "ASC NULLS LAST", scheduled_at: :asc, id: :asc }, + where: "finished_at IS NULL AND locked_by_id IS NULL", + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092225_add_index_good_jobs_priority_scheduled_at.rb b/db/migrate/20261019092225_add_index_good_jobs_priority_scheduled_at.rb new file mode 100644 index 0000000000..c4fdb8e7a9 --- /dev/null +++ b/db/migrate/20261019092225_add_index_good_jobs_priority_scheduled_at.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsPriorityScheduledAt < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + reversible do |dir| + dir.up do + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.index_name_exists?(:good_jobs, "index_good_jobs_on_priority_scheduled_at_unfinished") && + connection.index_name_exists?(:good_jobs, "index_good_jobs_on_queue_name_priority_scheduled_at_unfinished") + end + end + + add_index :good_jobs, [:priority, :scheduled_at, :id], + where: "finished_at IS NULL", name: "index_good_jobs_on_priority_scheduled_at_unfinished", + algorithm: :concurrently + add_index :good_jobs, [:queue_name, :scheduled_at, :id], + where: "finished_at IS NULL", name: "index_good_jobs_on_queue_name_priority_scheduled_at_unfinished", + algorithm: :concurrently + end +end diff --git a/db/migrate/20261019092226_add_index_good_jobs_queue_name.rb b/db/migrate/20261019092226_add_index_good_jobs_queue_name.rb new file mode 100644 index 0000000000..ba0b783562 --- /dev/null +++ b/db/migrate/20261019092226_add_index_good_jobs_queue_name.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsQueueName < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, :queue_name, + name: :index_good_jobs_on_queue_name, + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092227_add_index_good_jobs_created_at.rb b/db/migrate/20261019092227_add_index_good_jobs_created_at.rb new file mode 100644 index 0000000000..f7354ada74 --- /dev/null +++ b/db/migrate/20261019092227_add_index_good_jobs_created_at.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsCreatedAt < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, :created_at, + name: :index_good_jobs_on_created_at, + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092228_add_index_good_jobs_discarded.rb b/db/migrate/20261019092228_add_index_good_jobs_discarded.rb new file mode 100644 index 0000000000..82c2629f63 --- /dev/null +++ b/db/migrate/20261019092228_add_index_good_jobs_discarded.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsDiscarded < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, :finished_at, + name: :index_good_jobs_on_discarded, + order: { finished_at: :desc }, + where: "finished_at IS NOT NULL AND error IS NOT NULL", + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092229_add_index_good_jobs_scheduled_at_and_queue_name.rb b/db/migrate/20261019092229_add_index_good_jobs_scheduled_at_and_queue_name.rb new file mode 100644 index 0000000000..5f5779fa12 --- /dev/null +++ b/db/migrate/20261019092229_add_index_good_jobs_scheduled_at_and_queue_name.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsScheduledAtAndQueueName < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, [:scheduled_at, :queue_name], + name: :index_good_jobs_on_scheduled_at_and_queue_name, + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092230_add_index_good_jobs_on_unfinished_or_errored.rb b/db/migrate/20261019092230_add_index_good_jobs_on_unfinished_or_errored.rb new file mode 100644 index 0000000000..f2b31a652e --- /dev/null +++ b/db/migrate/20261019092230_add_index_good_jobs_on_unfinished_or_errored.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsOnUnfinishedOrErrored < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, :id, + name: :index_good_jobs_on_unfinished_or_errored, + where: "finished_at IS NULL OR error IS NOT NULL", + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092231_add_index_good_jobs_discarded_job_class.rb b/db/migrate/20261019092231_add_index_good_jobs_discarded_job_class.rb new file mode 100644 index 0000000000..81f854a366 --- /dev/null +++ b/db/migrate/20261019092231_add_index_good_jobs_discarded_job_class.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsDiscardedJobClass < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, [:job_class, :finished_at], + name: :index_good_jobs_on_discarded_job_class, + where: "finished_at IS NOT NULL AND error IS NOT NULL", + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092232_add_index_good_jobs_dequeue_by_queue.rb b/db/migrate/20261019092232_add_index_good_jobs_dequeue_by_queue.rb new file mode 100644 index 0000000000..aa59d17d43 --- /dev/null +++ b/db/migrate/20261019092232_add_index_good_jobs_dequeue_by_queue.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddIndexGoodJobsDequeueByQueue < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_jobs, [:queue_name, :priority, :created_at], + name: :index_good_jobs_dequeue_by_queue, + order: { priority: "ASC NULLS LAST", created_at: :asc }, + where: "finished_at IS NULL AND locked_by_id IS NULL", + algorithm: :concurrently, + if_not_exists: true + + add_index :good_jobs, [:queue_name, :priority, :scheduled_at], + name: :index_good_jobs_dequeue_by_queue_scheduled_at, + order: { priority: "ASC NULLS LAST", scheduled_at: :asc }, + where: "finished_at IS NULL AND locked_by_id IS NULL", + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092233_add_index_good_job_executions_on_scheduled_at.rb b/db/migrate/20261019092233_add_index_good_job_executions_on_scheduled_at.rb new file mode 100644 index 0000000000..c006d36290 --- /dev/null +++ b/db/migrate/20261019092233_add_index_good_job_executions_on_scheduled_at.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class AddIndexGoodJobExecutionsOnScheduledAt < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_job_executions, :scheduled_at, + name: :index_good_job_executions_on_scheduled_at, + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092234_add_batch_query_indexes.rb b/db/migrate/20261019092234_add_batch_query_indexes.rb new file mode 100644 index 0000000000..00121301a2 --- /dev/null +++ b/db/migrate/20261019092234_add_batch_query_indexes.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class AddBatchQueryIndexes < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def change + add_index :good_job_batches, :finished_at, + name: :index_good_job_batches_on_finished_at, + where: "finished_at IS NOT NULL", + algorithm: :concurrently, + if_not_exists: true + add_index :good_job_batches, [:created_at, :id], + name: :index_good_job_batches_on_created_at_and_id, + order: { created_at: :desc, id: :desc }, + algorithm: :concurrently, + if_not_exists: true + add_index :good_jobs, :batch_id, + name: :index_good_jobs_on_batch_id_unfinished, + where: "batch_id IS NOT NULL AND finished_at IS NULL", + algorithm: :concurrently, + if_not_exists: true + add_index :good_jobs, :batch_callback_id, + name: :index_good_jobs_on_batch_callback_id_unfinished, + where: "batch_callback_id IS NOT NULL AND finished_at IS NULL", + algorithm: :concurrently, + if_not_exists: true + end +end diff --git a/db/migrate/20261019092235_remove_redundant_good_jobs_indexes.rb b/db/migrate/20261019092235_remove_redundant_good_jobs_indexes.rb new file mode 100644 index 0000000000..9b7a73c8e1 --- /dev/null +++ b/db/migrate/20261019092235_remove_redundant_good_jobs_indexes.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +class RemoveRedundantGoodJobsIndexes < ActiveRecord::Migration[8.1] + disable_ddl_transaction! + + def up + remove_index( + :good_jobs, + name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished, + algorithm: :concurrently, + if_exists: true + ) + remove_index( + :good_jobs, + name: :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked, + algorithm: :concurrently, + if_exists: true + ) + remove_index( + :good_jobs, + name: :index_good_jobs_on_queue_name_and_scheduled_at, + algorithm: :concurrently, + if_exists: true + ) + end + + def down + add_index( + :good_jobs, + [:priority, :created_at], + name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished, + order: { priority: "DESC NULLS LAST", created_at: :asc }, + where: "finished_at IS NULL", + algorithm: :concurrently, + if_not_exists: true + ) + add_index( + :good_jobs, + [:priority, :scheduled_at], + name: :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked, + order: { priority: "ASC NULLS LAST", scheduled_at: :asc }, + where: "finished_at IS NULL AND locked_by_id IS NULL", + algorithm: :concurrently, + if_not_exists: true + ) + add_index( + :good_jobs, + [:queue_name, :scheduled_at], + name: :index_good_jobs_on_queue_name_and_scheduled_at, + where: "finished_at IS NULL", + algorithm: :concurrently, + if_not_exists: true + ) + end +end diff --git a/db/migrate/20261019092236_reorder_good_jobs_cron_index.rb b/db/migrate/20261019092236_reorder_good_jobs_cron_index.rb new file mode 100644 index 0000000000..a8160b9fa8 --- /dev/null +++ b/db/migrate/20261019092236_reorder_good_jobs_cron_index.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +class ReorderGoodJobsCronIndex < ActiveRecord::Migration[8.1] + CURRENT_INDEX = :index_good_jobs_on_cron_key_and_cron_at_cond + REPLACEMENT_INDEX = :index_good_jobs_on_cron_key_and_cron_at_desc_cond + + disable_ddl_transaction! + + def up + return if cron_index_has_expected_order? + + add_index :good_jobs, [:cron_key, :cron_at], + name: REPLACEMENT_INDEX, + order: { cron_at: "DESC NULLS LAST" }, + where: "cron_key IS NOT NULL", + unique: true, + algorithm: :concurrently, + if_not_exists: true + remove_index :good_jobs, name: CURRENT_INDEX, algorithm: :concurrently, if_exists: true + rename_index :good_jobs, REPLACEMENT_INDEX, CURRENT_INDEX + end + + def down + return if cron_index_definition && !cron_index_has_expected_order? + + add_index :good_jobs, [:cron_key, :cron_at], + name: REPLACEMENT_INDEX, + where: "cron_key IS NOT NULL", + unique: true, + algorithm: :concurrently, + if_not_exists: true + remove_index :good_jobs, name: CURRENT_INDEX, algorithm: :concurrently, if_exists: true + rename_index :good_jobs, REPLACEMENT_INDEX, CURRENT_INDEX + end + + private + + def cron_index_has_expected_order? + cron_index_definition&.include?("cron_at DESC NULLS LAST") + end + + def cron_index_definition + connection.select_value(<<~SQL.squish) + SELECT indexdef + FROM pg_indexes + WHERE schemaname = ANY (current_schemas(false)) + AND tablename = #{connection.quote('good_jobs')} + AND indexname = #{connection.quote(CURRENT_INDEX.to_s)} + SQL + end +end diff --git a/db/migrate/20261019092237_create_good_job_concurrency_claims.rb b/db/migrate/20261019092237_create_good_job_concurrency_claims.rb new file mode 100644 index 0000000000..4f8ea32186 --- /dev/null +++ b/db/migrate/20261019092237_create_good_job_concurrency_claims.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class CreateGoodJobConcurrencyClaims < ActiveRecord::Migration[8.1] + def up + # Ensure this incremental update migration is idempotent + # with monolithic install migration. + return if connection.table_exists?(:good_job_concurrency_claims) + + create_table :good_job_concurrency_claims, id: :uuid do |t| + t.datetime :created_at, null: false + t.datetime :updated_at, null: false + t.uuid :job_id, null: false + t.uuid :locked_by_id + t.integer :state, limit: 2, null: false + t.text :key, null: false + + t.index [:key, :job_id], unique: true + t.index [:key, :state, :created_at], name: :index_good_job_concurrency_claims_for_promotion + t.index :job_id + t.index :locked_by_id, where: "locked_by_id IS NOT NULL" + end + end + + def down + drop_table :good_job_concurrency_claims, if_exists: true + end +end diff --git a/db/schema.rb b/db/schema.rb index b2346825d1..f68e698656 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_10_13_162501) do +ActiveRecord::Schema[8.1].define(version: 2026_10_19_092237) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "pg_stat_statements" @@ -18,117 +18,116 @@ enable_extension "pgcrypto" enable_extension "unaccent" - create_table "action_text_rich_texts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.text "body" - t.datetime "created_at", null: false + create_table "action_text_rich_texts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name", null: false - t.uuid "record_id", null: false + t.text "body" t.string "record_type", null: false + t.uuid "record_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true end create_table "active_hashcash_stamps", force: :cascade do |t| + t.string "version", null: false t.integer "bits", null: false - t.jsonb "context" - t.string "counter", null: false - t.datetime "created_at", null: false t.date "date", null: false + t.string "resource", null: false t.string "ext", null: false - t.string "ip_address" t.string "rand", null: false + t.string "counter", null: false t.string "request_path" - t.string "resource", null: false + t.string "ip_address" + t.jsonb "context" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "version", null: false t.index ["counter", "rand", "date", "resource", "bits", "version", "ext"], name: "index_active_hashcash_stamps_unique", unique: true t.index ["ip_address", "created_at"], name: "index_active_hashcash_stamps_on_ip_address_and_created_at", where: "(ip_address IS NOT NULL)" end - create_table "active_storage_attachments", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "active_storage_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name", null: false + t.string "record_type", null: false + t.uuid "record_id", null: false t.uuid "blob_id", null: false t.datetime "created_at", precision: nil, null: false t.datetime "deleted_at" - t.string "name", null: false - t.uuid "record_id", null: false - t.string "record_type", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true end - create_table "active_storage_blobs", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.bigint "byte_size", null: false - t.string "checksum" - t.string "content_type" - t.datetime "created_at", precision: nil, null: false - t.string "filename", null: false + create_table "active_storage_blobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "key", null: false + t.string "filename", null: false + t.string "content_type" t.text "metadata" t.string "service_name", null: false + t.bigint "byte_size", null: false + t.string "checksum" + t.datetime "created_at", precision: nil, null: false t.uuid "university_id" t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true t.index ["university_id"], name: "index_active_storage_blobs_on_university_id" end - create_table "active_storage_variant_records", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "active_storage_variant_records", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "blob_id", null: false t.string "variation_digest", null: false - t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end create_table "administration_academic_year_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "about_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" + t.uuid "university_id", null: false t.uuid "language_id", null: false t.string "slug" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_7962406d05", unique: true t.index ["about_id"], name: "index_administration_academic_year_localizations_on_about_id" t.index ["language_id"], name: "idx_on_language_id_a52fb1a1c1" t.index ["university_id"], name: "idx_on_university_id_31eabbc7a7" end - create_table "administration_academic_years", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" + create_table "administration_academic_years", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.integer "year" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["university_id"], name: "index_administration_academic_years_on_university_id" end create_table "administration_academic_years_university_people", id: false, force: :cascade do |t| - t.uuid "administration_academic_year_id", null: false t.uuid "university_person_id", null: false + t.uuid "administration_academic_year_id", null: false t.index ["administration_academic_year_id", "university_person_id"], name: "index_academic_year_person" t.index ["university_person_id", "administration_academic_year_id"], name: "index_person_academic_year" end create_table "administration_cohort_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "about_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" t.uuid "language_id", null: false - t.string "slug" t.uuid "university_id", null: false + t.string "slug" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_ae60ea28b0", unique: true t.index ["about_id"], name: "index_administration_cohort_localizations_on_about_id" t.index ["language_id"], name: "index_administration_cohort_localizations_on_language_id" t.index ["university_id"], name: "index_administration_cohort_localizations_on_university_id" end - create_table "administration_cohorts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "administration_cohorts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "program_id", null: false t.uuid "academic_year_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" t.string "name" - t.uuid "program_id", null: false - t.uuid "school_id", null: false - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "school_id", null: false + t.datetime "deleted_at" t.index ["academic_year_id"], name: "index_administration_cohorts_on_academic_year_id" t.index ["program_id"], name: "index_administration_cohorts_on_program_id" t.index ["school_id"], name: "index_administration_cohorts_on_school_id" @@ -143,22 +142,22 @@ end create_table "administration_location_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.string "address_additional" t.string "address_name" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.uuid "language_id" + t.text "featured_image_credit" t.string "meta_description" - t.string "name" t.string "slug" t.text "summary" + t.string "name" + t.string "url" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "url" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_cf0b216983", unique: true t.index ["about_id"], name: "index_administration_location_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_7befd34d61" @@ -167,106 +166,106 @@ end create_table "administration_locations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.string "address" + t.string "zipcode" t.string "city" t.string "country" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.float "latitude" t.float "longitude" t.string "phone" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "zipcode" + t.datetime "deleted_at" t.index ["university_id"], name: "index_administration_locations_on_university_id" end create_table "administration_locations_education_programs", id: false, force: :cascade do |t| - t.uuid "administration_location_id", null: false t.uuid "education_program_id", null: false + t.uuid "administration_location_id", null: false t.index ["administration_location_id", "education_program_id"], name: "index_program_location" t.index ["education_program_id", "administration_location_id"], name: "index_location_program" end create_table "administration_locations_education_schools", id: false, force: :cascade do |t| - t.uuid "administration_location_id", null: false t.uuid "education_school_id", null: false + t.uuid "administration_location_id", null: false t.index ["administration_location_id", "education_school_id"], name: "index_school_location" t.index ["education_school_id", "administration_location_id"], name: "index_location_school" end - create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.text "description" - t.text "name" + create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "number" + t.text "name" + t.text "description" + t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "administration_qualiopi_indicators", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false + create_table "administration_qualiopi_indicators", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "criterion_id", null: false - t.text "glossary" - t.text "level_expected" - t.text "name" - t.text "non_conformity" t.integer "number" + t.text "name" + t.text "level_expected" t.text "proof" t.text "requirement" + t.text "non_conformity" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.text "glossary" t.index ["criterion_id"], name: "index_administration_qualiopi_indicators_on_criterion_id" end - create_table "communication_blocks", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" + create_table "communication_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.string "about_type" - t.uuid "communication_website_id" - t.datetime "created_at", null: false + t.uuid "about_id" + t.integer "template_kind", default: 0, null: false t.jsonb "data" - t.datetime "deleted_at" - t.string "html_class" - t.jsonb "metadata" - t.string "migration_identifier" t.integer "position", null: false - t.boolean "published", default: true - t.integer "template_kind", default: 0, null: false - t.string "title" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "title" + t.boolean "published", default: true + t.uuid "communication_website_id" + t.string "migration_identifier" + t.string "html_class" + t.datetime "deleted_at" + t.jsonb "metadata" t.index ["about_type", "about_id"], name: "index_communication_website_blocks_on_about" t.index ["communication_website_id"], name: "index_communication_blocks_on_communication_website_id" t.index ["university_id", "template_kind"], name: "index_communication_blocks_on_university_id_and_template_kind" end - create_table "communication_extranet_connections", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" + create_table "communication_extranet_connections", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "extranet_id", null: false t.string "about_type" + t.uuid "about_id" t.datetime "created_at", null: false - t.uuid "extranet_id", null: false - t.uuid "university_id", null: false t.datetime "updated_at", null: false t.index ["about_type", "about_id"], name: "index_communication_extranet_connections_on_object" t.index ["extranet_id"], name: "index_communication_extranet_connections_on_extranet_id" t.index ["university_id"], name: "index_communication_extranet_connections_on_university_id" end - create_table "communication_extranet_document_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false + create_table "communication_extranet_document_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "extranet_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["extranet_id"], name: "index_communication_extranet_document_categories_on_extranet_id" t.index ["university_id"], name: "extranet_document_categories_universities" end create_table "communication_extranet_document_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" + t.string "name" t.uuid "about_id" - t.datetime "created_at", null: false - t.uuid "extranet_id" t.uuid "language_id" - t.string "name" - t.string "slug" + t.uuid "extranet_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_240480a272", unique: true t.index ["about_id"], name: "idx_on_about_id_23f2406431" @@ -276,13 +275,13 @@ end create_table "communication_extranet_document_kind_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" + t.string "name" t.uuid "about_id" - t.datetime "created_at", null: false - t.uuid "extranet_id" t.uuid "language_id" - t.string "name" - t.string "slug" + t.uuid "extranet_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_e6b3e9e1e9", unique: true t.index ["about_id"], name: "idx_on_about_id_0cd2750c0e" @@ -291,24 +290,24 @@ t.index ["university_id"], name: "idx_on_university_id_0dc1259072" end - create_table "communication_extranet_document_kinds", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false + create_table "communication_extranet_document_kinds", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "extranet_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["extranet_id"], name: "index_communication_extranet_document_kinds_on_extranet_id" t.index ["university_id"], name: "extranet_document_kinds_universities" end create_table "communication_extranet_document_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.uuid "extranet_id" - t.uuid "language_id" t.string "name" t.boolean "published", default: false t.datetime "published_at" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "extranet_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_6f86a27438", unique: true t.index ["about_id"], name: "idx_on_about_id_48b91d67ca" @@ -317,13 +316,13 @@ t.index ["university_id"], name: "idx_on_university_id_95419f1df4" end - create_table "communication_extranet_documents", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "category_id" - t.datetime "created_at", null: false - t.uuid "extranet_id", null: false - t.uuid "kind_id" + create_table "communication_extranet_documents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false + t.uuid "extranet_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "kind_id" + t.uuid "category_id" t.index ["category_id"], name: "extranet_document_categories" t.index ["extranet_id"], name: "index_communication_extranet_documents_on_extranet_id" t.index ["kind_id"], name: "index_extranet_document_kinds" @@ -331,18 +330,18 @@ end create_table "communication_extranet_invitations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false t.uuid "extranet_id" - t.string "from_email" - t.string "from_name" - t.text "message" + t.uuid "user_id" t.uuid "person_id" - t.string "to_email" - t.string "to_name" - t.string "token" t.uuid "university_id" + t.string "from_name" + t.string "from_email" + t.string "to_name" + t.string "to_email" + t.text "message" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.uuid "user_id" + t.string "token" t.index ["extranet_id"], name: "index_communication_extranet_invitations_on_extranet_id" t.index ["person_id"], name: "index_communication_extranet_invitations_on_person_id" t.index ["token"], name: "index_communication_extranet_invitations_on_token", unique: true @@ -351,48 +350,48 @@ end create_table "communication_extranet_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.text "cookies_policy" - t.datetime "created_at", null: false t.text "home_sentence" - t.string "invitation_message_automatic_subject", default: "" - t.text "invitation_message_automatic_text", default: "" - t.text "invitation_message_manual_signature" - t.string "invitation_message_manual_subject" - t.text "invitation_message_manual_text" - t.uuid "language_id" t.string "name" t.text "privacy_policy" - t.boolean "published", default: false - t.datetime "published_at" t.string "registration_contact" t.string "sso_button_label" t.text "terms" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "published", default: false + t.datetime "published_at" + t.string "invitation_message_automatic_subject", default: "" + t.text "invitation_message_automatic_text", default: "" + t.string "invitation_message_manual_subject" + t.text "invitation_message_manual_text" + t.text "invitation_message_manual_signature" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_2f61ef5d94", unique: true t.index ["about_id"], name: "index_communication_extranet_localizations_on_about_id" t.index ["language_id"], name: "index_communication_extranet_localizations_on_language_id" t.index ["university_id"], name: "index_communication_extranet_localizations_on_university_id" end - create_table "communication_extranet_post_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false + create_table "communication_extranet_post_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "extranet_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["extranet_id"], name: "index_communication_extranet_post_categories_on_extranet_id" t.index ["university_id"], name: "index_communication_extranet_post_categories_on_university_id" end create_table "communication_extranet_post_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" + t.string "name" t.uuid "about_id" - t.datetime "created_at", null: false - t.uuid "extranet_id" t.uuid "language_id" - t.string "name" - t.string "slug" + t.uuid "extranet_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_f29c05f164", unique: true t.index ["about_id"], name: "idx_on_about_id_ff80179dbe" @@ -402,21 +401,21 @@ end create_table "communication_extranet_post_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.uuid "extranet_id" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.uuid "language_id" - t.boolean "pinned", default: false + t.text "featured_image_credit" t.boolean "published", default: false + t.boolean "pinned", default: false t.datetime "published_at" t.string "slug" t.text "summary" t.string "title" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "extranet_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_01f6523e84", unique: true t.index ["about_id"], name: "index_communication_extranet_post_localizations_on_about_id" t.index ["extranet_id"], name: "index_communication_extranet_post_localizations_on_extranet_id" @@ -425,42 +424,42 @@ t.index ["university_id"], name: "idx_on_university_id_28188e2217" end - create_table "communication_extranet_posts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_extranet_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "author_id" - t.uuid "category_id" - t.datetime "created_at", null: false t.uuid "extranet_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "category_id" t.index ["author_id"], name: "index_communication_extranet_posts_on_author_id" t.index ["category_id"], name: "index_communication_extranet_posts_on_category_id" t.index ["extranet_id"], name: "index_communication_extranet_posts_on_extranet_id" t.index ["university_id"], name: "index_communication_extranet_posts_on_university_id" end - create_table "communication_extranets", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "about_type" - t.string "color" + create_table "communication_extranets", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.string "host" t.datetime "created_at", null: false - t.text "css" - t.uuid "default_language_id", null: false - t.boolean "feature_alumni", default: false - t.boolean "feature_contacts", default: false - t.boolean "feature_documents", default: false - t.boolean "feature_jobs", default: false - t.boolean "feature_posts", default: false + t.datetime "updated_at", null: false + t.string "about_type" + t.uuid "about_id" t.boolean "has_sso", default: false - t.string "host" - t.text "sass" t.text "sso_cert" t.jsonb "sso_mapping" t.string "sso_name_identifier_format" t.integer "sso_provider", default: 0 t.string "sso_target_url" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false - t.text "upper_menu", default: "" + t.string "color" + t.boolean "feature_alumni", default: false + t.boolean "feature_contacts", default: false + t.boolean "feature_documents", default: false + t.boolean "feature_posts", default: false + t.boolean "feature_jobs", default: false + t.text "sass" + t.text "css" + t.uuid "default_language_id", null: false + t.text "upper_menu", default: "" t.index ["about_type", "about_id"], name: "index_communication_extranets_on_about" t.index ["default_language_id"], name: "index_communication_extranets_on_default_language_id" t.index ["university_id"], name: "index_communication_extranets_on_university_id" @@ -468,38 +467,38 @@ create_table "communication_file_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "bodyclass" - t.datetime "created_at", null: false t.boolean "is_taxonomy", default: false - t.uuid "parent_id" t.integer "position", default: 0 t.integer "position_in_tree" t.uuid "university_id", null: false + t.uuid "parent_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["parent_id"], name: "index_communication_file_categories_on_parent_id" t.index ["university_id"], name: "index_communication_file_categories_on_university_id" end create_table "communication_file_categories_files", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "file_id", null: false + t.uuid "category_id", null: false t.index ["category_id"], name: "index_communication_file_categories_files_on_category_id" t.index ["file_id", "category_id"], name: "file_category" t.index ["file_id"], name: "index_communication_file_categories_files_on_file_id" end create_table "communication_file_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.text "featured_image_credit" - t.text "featured_media_alt" - t.uuid "featured_media_id" - t.uuid "language_id" - t.text "meta_description" - t.string "name" t.string "slug" + t.string "name" + t.text "featured_media_alt" + t.text "featured_image_credit" t.text "summary" + t.text "meta_description" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_f3d63b2051", unique: true t.index ["about_id"], name: "index_communication_file_category_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_f22926f084" @@ -508,13 +507,13 @@ end create_table "communication_file_contexts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.string "about_type" + t.uuid "about_id" t.uuid "communication_file_localization_id", null: false - t.uuid "communication_website_id" - t.datetime "created_at", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "communication_website_id" t.index ["about_type", "about_id"], name: "index_communication_file_contexts_on_about" t.index ["communication_file_localization_id"], name: "idx_on_communication_file_localization_id_a9a8fdc48e" t.index ["communication_website_id"], name: "index_communication_file_contexts_on_communication_website_id" @@ -522,31 +521,31 @@ end create_table "communication_file_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" - t.string "featured_media_alt" - t.uuid "featured_media_id" - t.string "file_server_current_checksum" - t.string "file_server_current_path" - t.string "file_server_slug" - t.text "internal_description" - t.uuid "language_id", null: false - t.text "meta_description" t.string "name" - t.uuid "original_blob_id", null: false + t.string "slug" + t.text "internal_description" t.bigint "original_byte_size" t.string "original_checksum" t.string "original_content_type" - t.string "original_extension", default: "" t.string "original_filename" - t.boolean "published", default: false - t.datetime "published_at" - t.string "slug" + t.uuid "original_blob_id", null: false + t.uuid "language_id", null: false + t.uuid "about_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "original_extension", default: "" + t.boolean "published", default: false + t.datetime "published_at" + t.text "meta_description" + t.datetime "deleted_at" t.uuid "updated_by_id" + t.string "featured_media_alt" + t.text "featured_image_credit" + t.uuid "featured_media_id" + t.string "file_server_slug" + t.string "file_server_current_path" + t.string "file_server_current_checksum" t.index ["about_id"], name: "index_communication_file_localizations_on_about_id" t.index ["featured_media_id"], name: "index_communication_file_localizations_on_featured_media_id" t.index ["language_id"], name: "index_communication_file_localizations_on_language_id" @@ -556,59 +555,59 @@ end create_table "communication_file_redirections", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_file_localization_id", null: false - t.datetime "created_at", null: false t.string "path" + t.uuid "communication_file_localization_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["communication_file_localization_id"], name: "idx_on_communication_file_localization_id_b5293392d9" t.index ["university_id"], name: "index_communication_file_redirections_on_university_id" end create_table "communication_files", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.uuid "created_by_id" t.datetime "deleted_at" t.boolean "is_lasting", default: true - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.index ["created_by_id"], name: "index_communication_files_on_created_by_id" t.index ["university_id"], name: "index_communication_files_on_university_id" end create_table "communication_media_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" - t.datetime "created_at", null: false t.boolean "is_taxonomy", default: false - t.uuid "parent_id" t.integer "position", null: false - t.integer "position_in_tree" t.uuid "university_id", null: false + t.uuid "parent_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "bodyclass" + t.integer "position_in_tree" t.index ["parent_id"], name: "index_communication_media_categories_on_parent_id" t.index ["university_id"], name: "index_communication_media_categories_on_university_id" end create_table "communication_media_categories_medias", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "media_id", null: false + t.uuid "category_id", null: false t.index ["category_id", "media_id"], name: "category_media" t.index ["media_id", "category_id"], name: "media_category" end create_table "communication_media_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.text "featured_image_credit" - t.text "featured_media_alt" - t.uuid "featured_media_id" - t.uuid "language_id" - t.text "meta_description" - t.string "name" t.string "slug" + t.string "name" + t.text "featured_media_alt" + t.text "featured_image_credit" t.text "summary" + t.text "meta_description" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_b290ff1c8d", unique: true t.index ["about_id"], name: "index_communication_media_category_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_c6035bfebf" @@ -617,15 +616,15 @@ end create_table "communication_media_collection_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false - t.datetime "created_at", null: false - t.text "featured_image_credit" + t.string "name" t.text "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" t.uuid "language_id", null: false - t.string "name" + t.uuid "about_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_378eb970df", unique: true t.index ["about_id"], name: "index_communication_media_collection_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_93012a8f51" @@ -634,22 +633,22 @@ end create_table "communication_media_collections", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["university_id"], name: "index_communication_media_collections_on_university_id" end create_table "communication_media_contexts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "about_type" - t.uuid "active_storage_blob_id", null: false t.uuid "communication_media_id", null: false - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.jsonb "crop_settings" + t.uuid "active_storage_blob_id", null: false + t.string "about_type" + t.uuid "about_id" t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "communication_website_id" + t.jsonb "crop_settings" t.index ["about_type", "about_id"], name: "index_communication_media_contexts_on_about" t.index ["active_storage_blob_id"], name: "index_communication_media_contexts_on_active_storage_blob_id" t.index ["communication_media_id"], name: "index_communication_media_contexts_on_communication_media_id" @@ -658,19 +657,19 @@ end create_table "communication_media_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false + t.string "name" t.text "alt" - t.datetime "created_at", null: false t.text "credit" - t.datetime "deleted_at" - t.text "internal_description" t.uuid "language_id", null: false - t.string "name" - t.boolean "published", default: false - t.datetime "published_at" + t.uuid "about_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.text "internal_description" + t.boolean "published", default: false + t.datetime "published_at" t.uuid "updated_by_id" + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_fec28c8838", unique: true t.index ["about_id"], name: "index_communication_media_localizations_on_about_id" t.index ["deleted_at"], name: "index_communication_media_localizations_on_deleted_at" @@ -680,19 +679,19 @@ end create_table "communication_medias", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_media_collection_id" - t.datetime "created_at", null: false - t.uuid "created_by_id" - t.datetime "deleted_at" t.integer "origin", default: 1, null: false - t.uuid "original_blob_id", null: false - t.bigint "original_byte_size" + t.string "original_filename" t.string "original_checksum" t.string "original_content_type" - t.string "original_extension", default: "" - t.string "original_filename" + t.bigint "original_byte_size" + t.uuid "original_blob_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "communication_media_collection_id" + t.string "original_extension", default: "" + t.uuid "created_by_id" + t.datetime "deleted_at" t.index ["communication_media_collection_id"], name: "idx_on_communication_media_collection_id_6cace98319" t.index ["created_by_id"], name: "index_communication_medias_on_created_by_id" t.index ["deleted_at"], name: "index_communication_medias_on_deleted_at" @@ -701,18 +700,18 @@ end create_table "communication_website_agenda_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + t.integer "position", null: false t.uuid "communication_website_id", null: false + t.uuid "university_id", null: false t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "parent_id" t.boolean "is_programs_root", default: false + t.uuid "program_id" t.boolean "is_taxonomy", default: false + t.string "bodyclass" t.string "migration_identifier" - t.uuid "parent_id" - t.integer "position", null: false t.integer "position_in_tree" - t.uuid "program_id" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.index ["communication_website_id"], name: "idx_communication_website_agenda_cats_on_website_id" t.index ["parent_id"], name: "index_communication_website_agenda_categories_on_parent_id" t.index ["program_id"], name: "index_communication_website_agenda_categories_on_program_id" @@ -720,8 +719,8 @@ end create_table "communication_website_agenda_categories_events", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "event_id", null: false + t.uuid "category_id", null: false t.index ["category_id", "event_id"], name: "category_event" t.index ["event_id", "category_id"], name: "event_category" end @@ -734,27 +733,27 @@ end create_table "communication_website_agenda_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "breadcrumb_title" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.text "header_text" - t.uuid "language_id" + t.text "featured_image_credit" t.text "meta_description" - t.string "migration_identifier" t.string "name" t.string "path" t.string "slug" - t.string "subtitle" t.text "summary" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.uuid "communication_website_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "migration_identifier" + t.string "subtitle" + t.string "breadcrumb_title" + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.text "header_text" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_e6b981c826", unique: true t.index ["about_id"], name: "idx_on_about_id_012efb471f" t.index ["communication_website_id"], name: "idx_on_communication_website_id_2eaea4d96e" @@ -765,12 +764,12 @@ end create_table "communication_website_agenda_event_days", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_website_agenda_event_id", null: false + t.uuid "university_id", null: false + t.uuid "language_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false + t.uuid "communication_website_agenda_event_id", null: false t.date "date" - t.uuid "language_id", null: false - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["communication_website_agenda_event_id"], name: "idx_on_communication_website_agenda_event_id_4defccd002" t.index ["communication_website_id"], name: "idx_on_communication_website_id_38a3895ffa" @@ -779,21 +778,11 @@ end create_table "communication_website_agenda_event_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.jsonb "add_to_calendar_urls" - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.uuid "language_id" + t.text "featured_image_credit" t.string "meta_description" t.string "migration_identifier" - t.text "notes" t.boolean "published", default: false t.datetime "published_at" t.string "slug" @@ -801,8 +790,18 @@ t.text "summary" t.text "text" t.string "title" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.text "notes" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_10e350e257", unique: true t.index ["about_id"], name: "idx_on_about_id_db6323806a" t.index ["communication_website_id"], name: "idx_on_communication_website_id_87f393a516" @@ -812,17 +811,17 @@ end create_table "communication_website_agenda_event_time_slot_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false - t.jsonb "add_to_calendar_urls" + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" + t.uuid "about_id", null: false t.uuid "language_id", null: false - t.string "migration_identifier" t.string "place" - t.string "slug" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.jsonb "add_to_calendar_urls" + t.string "slug" + t.string "migration_identifier" + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_899f31df1f", unique: true t.index ["about_id"], name: "idx_on_about_id_e52a2e12b0" t.index ["communication_website_id"], name: "idx_on_communication_website_id_526f156fed" @@ -831,36 +830,36 @@ end create_table "communication_website_agenda_event_time_slots", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_website_agenda_event_id", null: false + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false + t.uuid "communication_website_agenda_event_id", null: false t.datetime "datetime" - t.datetime "deleted_at" t.integer "duration" - t.string "migration_identifier" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "migration_identifier" + t.datetime "deleted_at" t.index ["communication_website_agenda_event_id"], name: "idx_on_communication_website_agenda_event_id_022d825cf7" t.index ["communication_website_id"], name: "idx_on_communication_website_id_c0ac516bb5" t.index ["university_id"], name: "idx_on_university_id_bca328e63c" end - create_table "communication_website_agenda_events", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + create_table "communication_website_agenda_events", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false + t.date "from_day" + t.date "to_day" + t.uuid "parent_id" t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "time_zone" + t.string "migration_identifier" t.uuid "created_by_id" - t.datetime "deleted_at" - t.date "from_day" + t.string "bodyclass" t.boolean "is_lasting", default: false + t.datetime "deleted_at" t.boolean "is_template", default: false - t.string "migration_identifier" - t.uuid "parent_id" t.uuid "template_id" - t.string "time_zone" - t.date "to_day" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.index ["communication_website_id"], name: "index_agenda_events_on_communication_website_id" t.index ["created_by_id"], name: "index_communication_website_agenda_events_on_created_by_id" t.index ["parent_id"], name: "index_communication_website_agenda_events_on_parent_id" @@ -869,31 +868,31 @@ end create_table "communication_website_agenda_exhibition_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false t.jsonb "add_to_calendar_urls" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" t.boolean "header_cta" t.string "header_cta_label" t.string "header_cta_url" - t.uuid "language_id", null: false t.string "meta_description" t.string "migration_identifier" - t.text "notes" - t.string "place" t.boolean "published", default: false t.datetime "published_at" t.string "slug" t.string "subtitle" t.text "summary" - t.text "text" t.string "title" + t.uuid "about_id", null: false + t.uuid "language_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "communication_website_id", null: false + t.text "text" + t.text "notes" + t.string "place" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_635cd53cee", unique: true t.index ["about_id"], name: "idx_on_about_id_a6e772a338" t.index ["communication_website_id"], name: "idx_on_communication_website_id_8261badeaa" @@ -903,31 +902,31 @@ end create_table "communication_website_agenda_exhibitions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false t.uuid "created_by_id" - t.datetime "deleted_at" t.date "from_day" - t.boolean "is_lasting", default: false + t.date "to_day" t.string "migration_identifier" t.string "time_zone" - t.date "to_day" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "bodyclass" + t.boolean "is_lasting", default: false + t.datetime "deleted_at" t.index ["communication_website_id"], name: "index_agenda_exhibitions_on_communication_website_id" t.index ["created_by_id"], name: "idx_on_created_by_id_c3766f3a0a" t.index ["university_id"], name: "idx_on_university_id_46e895f493" end create_table "communication_website_agenda_period_day_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.integer "events_count", default: 0 - t.uuid "language_id", null: false t.string "slug" + t.integer "events_count", default: 0 t.uuid "university_id", null: false + t.uuid "communication_website_id", null: false + t.uuid "language_id", null: false + t.uuid "about_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_b8b9e8269f", unique: true t.index ["about_id"], name: "idx_on_about_id_ff7b8b96ea" @@ -937,14 +936,14 @@ end create_table "communication_website_agenda_period_days", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.integer "value" + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.date "date" + t.uuid "year_id", null: false t.uuid "month_id", null: false - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "value" - t.uuid "year_id", null: false + t.date "date" t.index ["communication_website_id"], name: "idx_on_communication_website_id_54db819007" t.index ["month_id"], name: "index_communication_website_agenda_period_days_on_month_id" t.index ["university_id", "communication_website_id", "year_id", "month_id", "value"], name: "index_communication_website_agenda_period_days_unique", unique: true @@ -952,12 +951,12 @@ end create_table "communication_website_agenda_period_month_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" t.uuid "about_id" - t.uuid "communication_website_id" - t.datetime "created_at", null: false t.uuid "language_id" - t.string "slug" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_e69d0eb996", unique: true t.index ["about_id"], name: "idx_on_about_id_e3d3e69fcb" @@ -967,24 +966,24 @@ end create_table "communication_website_agenda_period_months", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false + t.uuid "year_id", null: false + t.integer "value" t.datetime "created_at", null: false - t.uuid "university_id", null: false t.datetime "updated_at", null: false - t.integer "value" - t.uuid "year_id", null: false t.index ["communication_website_id"], name: "idx_on_communication_website_id_49eaf81807" t.index ["university_id", "communication_website_id", "year_id", "value"], name: "index_communication_website_agenda_period_months_unique", unique: true t.index ["year_id"], name: "index_communication_website_agenda_period_months_on_year_id" end create_table "communication_website_agenda_period_year_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" t.uuid "about_id" - t.uuid "communication_website_id" - t.datetime "created_at", null: false t.uuid "language_id" - t.string "slug" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_65b759f0dd", unique: true t.index ["about_id"], name: "idx_on_about_id_9d0e59880a" @@ -994,32 +993,32 @@ end create_table "communication_website_agenda_period_years", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false + t.integer "value" t.datetime "created_at", null: false - t.boolean "needs_checking", default: false - t.uuid "university_id", null: false t.datetime "updated_at", null: false - t.integer "value" + t.boolean "needs_checking", default: false t.index ["communication_website_id"], name: "idx_on_communication_website_id_dd738e97d3" t.index ["university_id", "communication_website_id", "value"], name: "index_communication_website_agenda_period_years_unique", unique: true end create_table "communication_website_alert_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false + t.string "title" + t.string "slug" + t.text "description" t.boolean "cta", default: false t.string "cta_label" t.string "cta_url" - t.datetime "deleted_at" - t.text "description" - t.uuid "language_id", null: false t.boolean "published", default: false t.datetime "published_at" - t.string "slug" - t.string "title" + t.uuid "about_id", null: false + t.uuid "language_id", null: false + t.uuid "communication_website_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_d42c296af1", unique: true t.index ["about_id"], name: "index_communication_website_alert_localizations_on_about_id" t.index ["communication_website_id"], name: "idx_on_communication_website_id_419e31417f" @@ -1028,25 +1027,25 @@ end create_table "communication_website_alerts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.datetime "deleted_at" t.integer "kind", default: 0, null: false + t.uuid "communication_website_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["communication_website_id"], name: "index_communication_website_alerts_on_communication_website_id" t.index ["university_id"], name: "index_communication_website_alerts_on_university_id" end - create_table "communication_website_connections", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.uuid "direct_source_id" - t.string "direct_source_type" - t.uuid "indirect_object_id", null: false - t.string "indirect_object_type", null: false + create_table "communication_website_connections", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.uuid "website_id", null: false + t.string "indirect_object_type", null: false + t.uuid "indirect_object_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "direct_source_type" + t.uuid "direct_source_id" t.index ["direct_source_type", "direct_source_id"], name: "index_communication_website_connections_on_source" t.index ["indirect_object_type", "indirect_object_id"], name: "index_communication_website_connections_on_object" t.index ["university_id"], name: "index_communication_website_connections_on_university_id" @@ -1054,12 +1053,12 @@ end create_table "communication_website_content_federations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false - t.string "about_type", null: false + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false + t.string "about_type", null: false + t.uuid "about_id", null: false t.uuid "destination_website_id", null: false - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["about_type", "about_id"], name: "index_communication_website_content_federations_on_about" t.index ["communication_website_id"], name: "idx_on_communication_website_id_ca52307519" @@ -1068,46 +1067,46 @@ end create_table "communication_website_federations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "destination_website_id", null: false t.uuid "source_website_id", null: false + t.uuid "destination_website_id", null: false t.index ["destination_website_id"], name: "idx_on_destination_website_id_f782caba64" t.index ["source_website_id"], name: "index_communication_website_federations_on_source_website_id" end create_table "communication_website_git_file_layouts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false t.string "path" + t.uuid "communication_website_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["communication_website_id"], name: "idx_on_communication_website_id_eb9ee4bc34" t.index ["university_id"], name: "index_communication_website_git_file_layouts_on_university_id" end create_table "communication_website_git_file_orphans", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false t.string "path" + t.uuid "communication_website_id", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["communication_website_id"], name: "idx_on_communication_website_id_18bd864000" t.index ["university_id"], name: "index_communication_website_git_file_orphans_on_university_id" end - create_table "communication_website_git_files", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" + create_table "communication_website_git_files", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "previous_path" t.string "about_type" + t.uuid "about_id" + t.uuid "website_id", null: false t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "previous_sha" t.string "current_path" t.string "current_sha" t.boolean "desynchronized", default: true t.datetime "desynchronized_at" - t.datetime "generated_at" - t.string "previous_path" - t.string "previous_sha" t.uuid "university_id" - t.datetime "updated_at", null: false - t.uuid "website_id", null: false + t.datetime "generated_at" t.index ["about_type", "about_id"], name: "index_communication_website_github_files_on_about" t.index ["desynchronized_at"], name: "index_communication_website_git_files_on_desynchronized_at" t.index ["university_id"], name: "index_communication_website_git_files_on_university_id" @@ -1116,17 +1115,17 @@ end create_table "communication_website_jobboard_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false + t.integer "position", null: false t.boolean "is_programs_root", default: false t.boolean "is_taxonomy", default: false + t.string "bodyclass" t.string "migration_identifier" - t.uuid "parent_id" - t.integer "position", null: false t.integer "position_in_tree" t.uuid "program_id" + t.uuid "parent_id" + t.uuid "communication_website_id", null: false t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["communication_website_id"], name: "idx_on_communication_website_id_b870d88a86" t.index ["parent_id"], name: "index_communication_website_jobboard_categories_on_parent_id" @@ -1135,34 +1134,34 @@ end create_table "communication_website_jobboard_categories_jobs", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "job_id", null: false + t.uuid "category_id", null: false t.index ["category_id", "job_id"], name: "category_job" t.index ["job_id", "category_id"], name: "job_category" end create_table "communication_website_jobboard_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "breadcrumb_title" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.text "header_text" - t.uuid "language_id" + t.text "featured_image_credit" t.text "meta_description" - t.string "migration_identifier" t.string "name" t.string "path" t.string "slug" - t.string "subtitle" t.text "summary" + t.string "migration_identifier" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.uuid "communication_website_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "subtitle" + t.string "breadcrumb_title" + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.text "header_text" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_3473524a0e", unique: true t.index ["about_id"], name: "idx_on_about_id_973f5413e1" t.index ["communication_website_id"], name: "idx_on_communication_website_id_1bf1f14ca6" @@ -1173,27 +1172,27 @@ end create_table "communication_website_jobboard_job_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.uuid "language_id" + t.text "featured_image_credit" t.string "meta_description" t.string "migration_identifier" t.boolean "published", default: false t.datetime "published_at" t.string "slug" t.string "subtitle" - t.text "summary" t.string "title" + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.text "summary" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_7944779395", unique: true t.index ["about_id"], name: "idx_on_about_id_8bbb00c89f" t.index ["communication_website_id"], name: "idx_on_communication_website_id_3e7b95d239" @@ -1204,15 +1203,15 @@ create_table "communication_website_jobboard_jobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "bodyclass" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.uuid "created_by_id" - t.datetime "deleted_at" t.date "from_day" - t.string "migration_identifier" t.date "to_day" t.uuid "university_id", null: false + t.uuid "communication_website_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "created_by_id" + t.string "migration_identifier" + t.datetime "deleted_at" t.index ["communication_website_id"], name: "index_jobboard_jobs_on_communication_website_id" t.index ["created_by_id"], name: "index_communication_website_jobboard_jobs_on_created_by_id" t.index ["university_id"], name: "index_communication_website_jobboard_jobs_on_university_id" @@ -1220,46 +1219,46 @@ create_table "communication_website_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "about_id", null: false - t.datetime "created_at", null: false t.uuid "language_id", null: false + t.uuid "university_id", null: false t.string "name" - t.boolean "published", default: false - t.datetime "published_at" t.string "social_email" - t.string "social_facebook" - t.string "social_github" - t.string "social_instagram" - t.string "social_linkedin" t.string "social_mastodon" t.string "social_peertube" - t.string "social_tiktok" - t.string "social_vimeo" t.string "social_x" + t.string "social_github" + t.string "social_linkedin" t.string "social_youtube" - t.uuid "university_id", null: false + t.string "social_vimeo" + t.string "social_instagram" + t.string "social_facebook" + t.string "social_tiktok" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "published", default: false + t.datetime "published_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_3a4954d1d9", unique: true t.index ["about_id"], name: "index_communication_website_localizations_on_about_id" t.index ["language_id"], name: "index_communication_website_localizations_on_language_id" t.index ["university_id"], name: "index_communication_website_localizations_on_university_id" end - create_table "communication_website_menu_items", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "about_type" - t.datetime "created_at", null: false - t.string "html_class" - t.integer "kind", default: 0 + create_table "communication_website_menu_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "website_id", null: false t.uuid "menu_id", null: false - t.uuid "parent_id" + t.string "title" t.integer "position", null: false - t.integer "position_in_tree" - t.boolean "should_open_new_tab", default: false - t.string "title" - t.uuid "university_id", null: false + t.integer "kind", default: 0 + t.uuid "parent_id" + t.string "about_type" + t.uuid "about_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.text "url" - t.uuid "website_id", null: false + t.boolean "should_open_new_tab", default: false + t.integer "position_in_tree" + t.string "html_class" t.index ["about_type", "about_id"], name: "index_communication_website_menu_items_on_about" t.index ["menu_id"], name: "index_communication_website_menu_items_on_menu_id" t.index ["parent_id"], name: "index_communication_website_menu_items_on_parent_id" @@ -1267,33 +1266,33 @@ t.index ["website_id"], name: "index_communication_website_menu_items_on_website_id" end - create_table "communication_website_menus", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.boolean "automatic", default: true + create_table "communication_website_menus", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.string "identifier" - t.uuid "language_id", null: false t.string "title" - t.uuid "university_id", null: false + t.string "identifier" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "language_id", null: false + t.boolean "automatic", default: true t.index ["communication_website_id"], name: "idx_comm_website_menus_on_communication_website_id" t.index ["language_id"], name: "index_communication_website_menus_on_language_id" t.index ["university_id"], name: "index_communication_website_menus_on_university_id" end create_table "communication_website_page_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false - t.boolean "is_programs_root", default: false t.boolean "is_taxonomy", default: false - t.string "migration_identifier" - t.uuid "parent_id" t.integer "position", null: false - t.integer "position_in_tree" - t.uuid "program_id" + t.uuid "communication_website_id", null: false + t.uuid "parent_id" t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "migration_identifier" + t.uuid "program_id" + t.boolean "is_programs_root", default: false + t.string "bodyclass" + t.integer "position_in_tree" t.index ["communication_website_id"], name: "idx_communication_website_page_cats_on_website_id" t.index ["parent_id"], name: "index_communication_website_page_categories_on_parent_id" t.index ["program_id"], name: "index_communication_website_page_categories_on_program_id" @@ -1301,34 +1300,34 @@ end create_table "communication_website_page_categories_pages", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "page_id", null: false + t.uuid "category_id", null: false t.index ["category_id", "page_id"], name: "idx_on_category_id_page_id_297597f98e" t.index ["page_id", "category_id"], name: "idx_on_page_id_category_id_c403d20e7a" end create_table "communication_website_page_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name" + t.string "slug" + t.string "path" + t.text "meta_description" + t.text "summary" + t.text "featured_media_alt" + t.text "featured_image_credit" t.uuid "about_id" - t.string "breadcrumb_title" + t.uuid "language_id" t.uuid "communication_website_id", null: false + t.uuid "university_id" t.datetime "created_at", null: false - t.text "featured_image_credit" - t.text "featured_media_alt" - t.uuid "featured_media_id" + t.datetime "updated_at", null: false + t.string "migration_identifier" + t.string "subtitle" + t.string "breadcrumb_title" t.boolean "header_cta", default: false t.string "header_cta_label" t.string "header_cta_url" t.text "header_text" - t.uuid "language_id" - t.text "meta_description" - t.string "migration_identifier" - t.string "name" - t.string "path" - t.string "slug" - t.string "subtitle" - t.text "summary" - t.uuid "university_id" - t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_c8a6e141bc", unique: true t.index ["about_id"], name: "idx_on_about_id_6c76163c36" t.index ["communication_website_id"], name: "idx_on_communication_website_id_f605face95" @@ -1338,30 +1337,30 @@ end create_table "communication_website_page_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.string "breadcrumb_title" - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" t.boolean "header_cta" t.string "header_cta_label" t.string "header_cta_url" t.text "header_text" - t.uuid "language_id" t.string "meta_description" t.string "migration_identifier" t.boolean "published" t.datetime "published_at" t.string "slug" - t.string "subtitle" t.text "summary" t.text "text" t.string "title" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" + t.string "subtitle" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_44e0a2bf9b", unique: true t.index ["about_id"], name: "index_communication_website_page_localizations_on_about_id" t.index ["communication_website_id"], name: "idx_on_communication_website_id_64c4831480" @@ -1370,55 +1369,55 @@ t.index ["university_id"], name: "idx_on_university_id_e62b2aba53" end - create_table "communication_website_pages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + create_table "communication_website_pages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false + t.text "path" + t.uuid "parent_id" + t.integer "position", null: false t.datetime "created_at", null: false - t.datetime "deleted_at" - t.boolean "full_width", default: false + t.datetime "updated_at", null: false t.integer "kind" + t.string "bodyclass" + t.boolean "full_width", default: false + t.string "type" t.string "migration_identifier" - t.uuid "parent_id" - t.text "path" - t.integer "position", null: false t.integer "position_in_tree" - t.string "type" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["communication_website_id", "type"], name: "idx_on_communication_website_id_type_66132928af", unique: true, where: "(type IS NOT NULL)" t.index ["communication_website_id"], name: "index_communication_website_pages_on_communication_website_id" t.index ["parent_id"], name: "index_communication_website_pages_on_parent_id" t.index ["university_id"], name: "index_communication_website_pages_on_university_id" end - create_table "communication_website_permalinks", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" + create_table "communication_website_permalinks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "website_id", null: false t.string "about_type" + t.uuid "about_id" + t.string "path" t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "is_current", default: true - t.string "path" t.string "target_url" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false - t.uuid "website_id", null: false t.index ["about_type", "about_id"], name: "index_communication_website_permalinks_on_about" t.index ["university_id"], name: "index_communication_website_permalinks_on_university_id" t.index ["website_id"], name: "index_communication_website_permalinks_on_website_id" end create_table "communication_website_portfolio_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" - t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false t.boolean "is_programs_root", default: false - t.boolean "is_taxonomy", default: false - t.string "migration_identifier" - t.uuid "parent_id" t.integer "position", null: false - t.integer "position_in_tree" - t.uuid "program_id" + t.uuid "communication_website_id", null: false + t.uuid "parent_id" t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "is_taxonomy", default: false + t.uuid "program_id" + t.string "bodyclass" + t.integer "position_in_tree" + t.string "migration_identifier" t.index ["communication_website_id"], name: "idx_on_communication_website_id_8f309901d4" t.index ["parent_id"], name: "index_communication_website_portfolio_categories_on_parent_id" t.index ["program_id"], name: "index_communication_website_portfolio_categories_on_program_id" @@ -1433,27 +1432,27 @@ end create_table "communication_website_portfolio_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "breadcrumb_title" - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.text "featured_image_credit" t.text "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.text "header_text" - t.uuid "language_id" + t.text "featured_image_credit" t.text "meta_description" - t.string "migration_identifier" t.string "name" t.string "path" t.string "slug" - t.string "subtitle" t.text "summary" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "migration_identifier" + t.string "subtitle" + t.string "breadcrumb_title" + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.text "header_text" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_4031c42a61", unique: true t.index ["about_id"], name: "idx_on_about_id_e184bfe637" t.index ["communication_website_id"], name: "idx_on_communication_website_id_9d28ee55e4" @@ -1463,27 +1462,27 @@ end create_table "communication_website_portfolio_project_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.uuid "language_id" + t.text "featured_image_credit" t.string "meta_description" t.string "migration_identifier" t.boolean "published", default: false t.datetime "published_at" t.string "slug" - t.string "subtitle" t.text "summary" t.string "title" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "communication_website_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "subtitle" + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_84c7b116b5", unique: true t.index ["about_id"], name: "idx_on_about_id_a668ef6090" t.index ["communication_website_id"], name: "idx_on_communication_website_id_e653b6273a" @@ -1493,35 +1492,35 @@ end create_table "communication_website_portfolio_projects", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + t.integer "year" t.uuid "communication_website_id", null: false + t.uuid "university_id", null: false t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.uuid "created_by_id" - t.datetime "deleted_at" - t.date "from_day" t.boolean "full_width", default: true + t.string "bodyclass" + t.datetime "deleted_at" t.string "migration_identifier" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false - t.integer "year" + t.date "from_day" t.index ["communication_website_id"], name: "idx_on_communication_website_id_aac12e3adb" t.index ["created_by_id"], name: "idx_on_created_by_id_7009ee99c6" t.index ["university_id"], name: "idx_on_university_id_ac2f4a0bfc" end - create_table "communication_website_post_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + create_table "communication_website_post_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false + t.integer "position", null: false t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "parent_id" + t.uuid "program_id" t.boolean "is_programs_root", default: false t.boolean "is_taxonomy", default: false + t.string "bodyclass" t.string "migration_identifier" - t.uuid "parent_id" - t.integer "position", null: false t.integer "position_in_tree" - t.uuid "program_id" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.index ["communication_website_id"], name: "idx_communication_website_post_cats_on_communication_website_id" t.index ["parent_id"], name: "index_communication_website_post_categories_on_parent_id" t.index ["program_id"], name: "index_communication_website_post_categories_on_program_id" @@ -1529,34 +1528,34 @@ end create_table "communication_website_post_categories_posts", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "post_id", null: false + t.uuid "category_id", null: false t.index ["category_id", "post_id"], name: "category_post" t.index ["post_id", "category_id"], name: "post_category" end create_table "communication_website_post_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "featured_media_alt" + t.text "featured_image_credit" + t.string "name" + t.text "meta_description" + t.string "slug" + t.string "path" + t.text "summary" t.uuid "about_id" - t.string "breadcrumb_title" + t.uuid "university_id", null: false + t.uuid "language_id", null: false t.uuid "communication_website_id", null: false t.datetime "created_at", null: false - t.text "featured_image_credit" - t.string "featured_media_alt" - t.uuid "featured_media_id" + t.datetime "updated_at", null: false + t.string "migration_identifier" + t.string "subtitle" + t.string "breadcrumb_title" t.boolean "header_cta", default: false t.string "header_cta_label" t.string "header_cta_url" t.text "header_text" - t.uuid "language_id", null: false - t.text "meta_description" - t.string "migration_identifier" - t.string "name" - t.string "path" - t.string "slug" - t.string "subtitle" - t.text "summary" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_94336f5680", unique: true t.index ["about_id"], name: "idx_on_about_id_6e430d4efc" t.index ["communication_website_id"], name: "idx_on_communication_website_id_0c06c1ae6f" @@ -1566,51 +1565,51 @@ end create_table "communication_website_post_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.uuid "communication_website_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.boolean "header_cta", default: false - t.string "header_cta_label" - t.string "header_cta_url" - t.uuid "language_id" + t.text "featured_image_credit" t.text "meta_description" t.string "migration_identifier" t.boolean "pinned" - t.uuid "publication_job_id" t.boolean "published" t.datetime "published_at" t.string "slug" - t.string "subtitle" t.text "summary" t.string "title" + t.uuid "about_id" + t.uuid "language_id" + t.uuid "communication_website_id" t.uuid "university_id" - t.uuid "unpublication_job_id" - t.datetime "unpublished_at" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_57307f7184", unique: true - t.index ["about_id"], name: "index_communication_website_post_localizations_on_about_id" - t.index ["communication_website_id"], name: "idx_on_communication_website_id_f6354f61f0" - t.index ["featured_media_id"], name: "idx_on_featured_media_id_3f383f239a" - t.index ["language_id"], name: "index_communication_website_post_localizations_on_language_id" - t.index ["publication_job_id"], name: "idx_on_publication_job_id_790971fcf1" - t.index ["university_id"], name: "idx_on_university_id_a3a3f1e954" + t.string "subtitle" + t.boolean "header_cta", default: false + t.string "header_cta_label" + t.string "header_cta_url" + t.uuid "publication_job_id" + t.datetime "deleted_at" + t.datetime "unpublished_at" + t.uuid "unpublication_job_id" + t.uuid "featured_media_id" + t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_57307f7184", unique: true + t.index ["about_id"], name: "index_communication_website_post_localizations_on_about_id" + t.index ["communication_website_id"], name: "idx_on_communication_website_id_f6354f61f0" + t.index ["featured_media_id"], name: "idx_on_featured_media_id_3f383f239a" + t.index ["language_id"], name: "index_communication_website_post_localizations_on_language_id" + t.index ["publication_job_id"], name: "idx_on_publication_job_id_790971fcf1" + t.index ["university_id"], name: "idx_on_university_id_a3a3f1e954" t.index ["unpublication_job_id"], name: "idx_on_unpublication_job_id" end - create_table "communication_website_posts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + create_table "communication_website_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false t.datetime "created_at", null: false - t.datetime "deleted_at" + t.datetime "updated_at", null: false + t.string "migration_identifier" t.boolean "full_width", default: false + t.string "bodyclass" t.boolean "is_lasting", default: false - t.string "migration_identifier" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["communication_website_id"], name: "index_communication_website_posts_on_communication_website_id" t.index ["university_id"], name: "index_communication_website_posts_on_university_id" end @@ -1623,9 +1622,9 @@ end create_table "communication_website_showcase_tags", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false t.string "name" t.string "slug" + t.datetime "created_at", null: false t.datetime "updated_at", null: false end @@ -1637,63 +1636,63 @@ end create_table "communication_website_variables", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "communication_website_id", null: false - t.datetime "created_at", null: false t.integer "key", null: false - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.string "value" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.index ["communication_website_id", "key"], name: "idx_on_communication_website_id_key_682d89f654", unique: true t.index ["university_id"], name: "index_communication_website_variables_on_university_id" end - create_table "communication_websites", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.string "about_type" - t.string "access_token" - t.text "apache_config_custom_content" - t.boolean "archive_content", default: false - t.boolean "autoupdate_theme", default: true + create_table "communication_websites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.string "url" t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "access_token" + t.string "repository" + t.string "about_type" + t.uuid "about_id" + t.integer "git_provider", default: 0 + t.string "git_endpoint" + t.text "style" + t.date "style_updated_at" + t.string "plausible_url" + t.string "git_branch" + t.boolean "in_production", default: false t.uuid "default_language_id", null: false - t.string "default_time_zone" + t.string "theme_version", default: "NA" t.text "deployment_status_badge" - t.string "deuxfleurs_access_key_id" + t.boolean "autoupdate_theme", default: true + t.boolean "feature_posts", default: true + t.boolean "feature_agenda", default: false t.boolean "deuxfleurs_hosting", default: true t.string "deuxfleurs_identifier" - t.string "deuxfleurs_secret_access_key" - t.boolean "feature_agenda", default: false - t.boolean "feature_alerts", default: false - t.boolean "feature_alumni", default: false - t.boolean "feature_hourly_publication", default: false - t.boolean "feature_jobboard", default: false + t.string "default_time_zone" t.boolean "feature_portfolio", default: false - t.boolean "feature_posts", default: true - t.boolean "feature_unpublication_date", default: false - t.string "git_branch" - t.string "git_endpoint" + t.boolean "in_showcase", default: true + t.datetime "locked_at" t.datetime "git_files_analysed_at" - t.integer "git_provider", default: 0 t.boolean "highlighted_in_showcase", default: false - t.integer "hosting", default: 1, null: false - t.boolean "in_production", default: false + t.uuid "locked_by_job_id" + t.string "deuxfleurs_access_key_id" + t.string "deuxfleurs_secret_access_key" + t.datetime "last_sync_at" + t.boolean "feature_alumni", default: false + t.boolean "feature_jobboard", default: false + t.boolean "feature_alerts", default: false + t.boolean "archive_content", default: false + t.integer "years_before_archive_content", default: 3 + t.boolean "feature_hourly_publication", default: false t.datetime "in_production_at" - t.boolean "in_showcase", default: true + t.integer "hosting", default: 1, null: false + t.text "apache_config_custom_content" + t.boolean "feature_unpublication_date", default: false + t.uuid "synchronization_locked_by_id" t.boolean "kelmscott_active", default: false t.integer "kelmscott_sync_method" - t.datetime "last_sync_at" - t.datetime "locked_at" - t.uuid "locked_by_job_id" - t.string "plausible_url" - t.string "repository" - t.text "style" - t.date "style_updated_at" - t.uuid "synchronization_locked_by_id" - t.string "theme_version", default: "NA" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false - t.string "url" - t.integer "years_before_archive_content", default: 3 t.index ["about_type", "about_id"], name: "index_communication_websites_on_about" t.index ["default_language_id"], name: "index_communication_websites_on_default_language_id" t.index ["synchronization_locked_by_id"], name: "index_communication_websites_on_synchronization_locked_by_id" @@ -1714,85 +1713,85 @@ end create_table "education_diploma_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.text "accessibility" - t.text "contacts" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.text "duration" - t.text "evaluation" - t.uuid "language_id" t.string "name" - t.text "other" - t.text "pedagogy" - t.text "prerequisites" - t.text "pricing" - t.text "pricing_apprenticeship" - t.text "pricing_continuing" - t.text "pricing_initial" - t.text "registration" t.string "short_name" t.string "slug" t.text "summary" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.text "pedagogy" + t.text "evaluation" + t.text "registration" + t.text "prerequisites" + t.text "other" + t.text "pricing" + t.text "pricing_initial" + t.text "pricing_continuing" + t.text "pricing_apprenticeship" + t.text "accessibility" + t.text "contacts" + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_4afdfc320d", unique: true t.index ["about_id"], name: "index_education_diploma_localizations_on_about_id" t.index ["language_id"], name: "index_education_diploma_localizations_on_language_id" t.index ["university_id"], name: "index_education_diploma_localizations_on_university_id" end - create_table "education_diplomas", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "certification" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.integer "ects" + create_table "education_diplomas", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "level", default: 0 - t.integer "position", null: false t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "ects" + t.string "certification" + t.integer "position", null: false + t.datetime "deleted_at" t.index ["university_id"], name: "index_education_diplomas_on_university_id" end create_table "education_program_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" - t.datetime "created_at", null: false t.boolean "is_taxonomy", default: false - t.uuid "parent_id" t.integer "position", null: false - t.integer "position_in_tree" + t.uuid "parent_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "bodyclass" + t.integer "position_in_tree" t.index ["parent_id"], name: "index_education_program_categories_on_parent_id" t.index ["university_id"], name: "index_education_program_categories_on_university_id" end create_table "education_program_categories_programs", id: false, force: :cascade do |t| - t.uuid "category_id", null: false t.uuid "program_id", null: false + t.uuid "category_id", null: false t.index ["category_id", "program_id"], name: "category_program" t.index ["program_id", "category_id"], name: "program_category" end create_table "education_program_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" + t.string "name" t.uuid "about_id" - t.string "breadcrumb_title" + t.uuid "language_id" + t.uuid "university_id" t.datetime "created_at", null: false - t.text "featured_image_credit" + t.datetime "updated_at", null: false t.text "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" + t.text "meta_description" + t.text "summary" + t.string "subtitle" + t.string "breadcrumb_title" t.boolean "header_cta", default: false t.string "header_cta_label" t.string "header_cta_url" t.text "header_text" - t.uuid "language_id" - t.text "meta_description" - t.string "name" - t.string "slug" - t.string "subtitle" - t.text "summary" - t.uuid "university_id" - t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_a020d83b5c", unique: true t.index ["about_id"], name: "index_education_program_category_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_1545e9bc7c" @@ -1801,18 +1800,13 @@ end create_table "education_program_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.text "accessibility" t.text "contacts" t.text "content" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.string "duration" t.text "evaluation" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" - t.uuid "language_id" + t.text "featured_image_credit" t.text "meta_description" t.string "name" t.text "objectives" @@ -1835,9 +1829,14 @@ t.string "short_name" t.string "slug" t.text "summary" + t.string "url" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "url" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_9b56b45e58", unique: true t.index ["about_id"], name: "index_education_program_localizations_on_about_id" t.index ["featured_media_id"], name: "index_education_program_localizations_on_featured_media_id" @@ -1845,20 +1844,20 @@ t.index ["university_id"], name: "index_education_program_localizations_on_university_id" end - create_table "education_programs", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.boolean "apprenticeship" - t.string "bodyclass" + create_table "education_programs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.integer "capacity" t.boolean "continuing" t.datetime "created_at", null: false - t.datetime "deleted_at" + t.datetime "updated_at", null: false + t.uuid "parent_id" t.uuid "diploma_id" - t.uuid "downloadable_summary_id" t.boolean "initial" - t.uuid "parent_id" + t.boolean "apprenticeship" + t.string "bodyclass" t.boolean "qualiopi_certified", default: false - t.uuid "university_id", null: false - t.datetime "updated_at", null: false + t.datetime "deleted_at" + t.uuid "downloadable_summary_id" t.index ["diploma_id"], name: "index_education_programs_on_diploma_id" t.index ["downloadable_summary_id"], name: "index_education_programs_on_downloadable_summary_id" t.index ["parent_id"], name: "index_education_programs_on_parent_id" @@ -1873,8 +1872,8 @@ end create_table "education_programs_university_people", id: false, force: :cascade do |t| - t.uuid "education_program_id", null: false t.uuid "university_person_id", null: false + t.uuid "education_program_id", null: false t.index ["education_program_id", "university_person_id"], name: "index_program_person" t.index ["university_person_id", "education_program_id"], name: "index_person_program" end @@ -1886,148 +1885,176 @@ end create_table "education_school_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "slug" + t.string "name" + t.string "url" t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.uuid "language_id" - t.string "name" - t.string "slug" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "url" + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_2cadc1fe79", unique: true t.index ["about_id"], name: "index_education_school_localizations_on_about_id" t.index ["language_id"], name: "index_education_school_localizations_on_language_id" t.index ["university_id"], name: "index_education_school_localizations_on_university_id" end - create_table "education_schools", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "education_schools", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.string "address" + t.string "zipcode" t.string "city" t.string "country" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.float "latitude" t.float "longitude" - t.string "phone" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "zipcode" + t.string "phone" + t.datetime "deleted_at" t.index ["university_id"], name: "index_education_schools_on_university_id" end create_table "good_job_batches", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "callback_priority" - t.text "callback_queue_name" t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.text "description" - t.datetime "discarded_at" + t.jsonb "serialized_properties" + t.text "on_finish" + t.text "on_success" + t.text "on_discard" + t.text "callback_queue_name" + t.integer "callback_priority" t.datetime "enqueued_at" + t.datetime "discarded_at" t.datetime "finished_at" t.datetime "jobs_finished_at" - t.text "on_discard" - t.text "on_finish" - t.text "on_success" - t.jsonb "serialized_properties" + t.index ["created_at", "id"], name: "index_good_job_batches_on_created_at_and_id", order: :desc + t.index ["finished_at"], name: "index_good_job_batches_on_finished_at", where: "(finished_at IS NOT NULL)" + end + + create_table "good_job_concurrency_claims", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.uuid "job_id", null: false + t.uuid "locked_by_id" + t.integer "state", limit: 2, null: false + t.text "key", null: false + t.index ["job_id"], name: "index_good_job_concurrency_claims_on_job_id" + t.index ["key", "job_id"], name: "index_good_job_concurrency_claims_on_key_and_job_id", unique: true + t.index ["key", "state", "created_at"], name: "index_good_job_concurrency_claims_for_promotion" + t.index ["locked_by_id"], name: "index_good_job_concurrency_claims_on_locked_by_id", where: "(locked_by_id IS NOT NULL)" end create_table "good_job_executions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "active_job_id", null: false t.datetime "created_at", null: false - t.interval "duration" - t.text "error" - t.text "error_backtrace", array: true - t.integer "error_event", limit: 2 - t.datetime "finished_at" + t.datetime "updated_at", null: false + t.uuid "active_job_id", null: false t.text "job_class" - t.uuid "process_id" t.text "queue_name" - t.datetime "scheduled_at" t.jsonb "serialized_params" - t.datetime "updated_at", null: false + t.datetime "scheduled_at" + t.datetime "finished_at" + t.text "error" + t.integer "error_event", limit: 2 + t.text "error_backtrace", array: true + t.uuid "process_id" + t.interval "duration" t.index ["active_job_id", "created_at"], name: "index_good_job_executions_on_active_job_id_and_created_at" t.index ["process_id", "created_at"], name: "index_good_job_executions_on_process_id_and_created_at" + t.index ["scheduled_at"], name: "index_good_job_executions_on_scheduled_at" end create_table "good_job_processes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.datetime "created_at", null: false - t.integer "lock_type", limit: 2 - t.jsonb "state" t.datetime "updated_at", null: false + t.jsonb "state" + t.integer "lock_type", limit: 2 end create_table "good_job_settings", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.datetime "created_at", null: false - t.text "key" t.datetime "updated_at", null: false + t.text "key" t.jsonb "value" t.index ["key"], name: "index_good_job_settings_on_key", unique: true end create_table "good_jobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.text "queue_name" + t.integer "priority" + t.jsonb "serialized_params" + t.datetime "scheduled_at" + t.datetime "performed_at" + t.datetime "finished_at" + t.text "error" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.uuid "active_job_id" - t.uuid "batch_callback_id" - t.uuid "batch_id" t.text "concurrency_key" - t.datetime "created_at", null: false - t.datetime "cron_at" t.text "cron_key" - t.text "error" - t.integer "error_event", limit: 2 - t.integer "executions_count" - t.datetime "finished_at" + t.uuid "retried_good_job_id" + t.datetime "cron_at" + t.uuid "batch_id" + t.uuid "batch_callback_id" t.boolean "is_discrete" + t.integer "executions_count" t.text "job_class" + t.integer "error_event", limit: 2 t.text "labels", array: true - t.datetime "locked_at" t.uuid "locked_by_id" - t.datetime "performed_at" - t.integer "priority" - t.text "queue_name" - t.uuid "retried_good_job_id" - t.datetime "scheduled_at" - t.jsonb "serialized_params" - t.datetime "updated_at", null: false + t.datetime "locked_at" + t.integer "lock_type", limit: 2 t.index ["active_job_id", "created_at"], name: "index_good_jobs_on_active_job_id_and_created_at" t.index ["batch_callback_id"], name: "index_good_jobs_on_batch_callback_id", where: "(batch_callback_id IS NOT NULL)" + t.index ["batch_callback_id"], name: "index_good_jobs_on_batch_callback_id_unfinished", where: "((batch_callback_id IS NOT NULL) AND (finished_at IS NULL))" t.index ["batch_id"], name: "index_good_jobs_on_batch_id", where: "(batch_id IS NOT NULL)" + t.index ["batch_id"], name: "index_good_jobs_on_batch_id_unfinished", where: "((batch_id IS NOT NULL) AND (finished_at IS NULL))" t.index ["concurrency_key", "created_at"], name: "index_good_jobs_on_concurrency_key_and_created_at" t.index ["concurrency_key"], name: "index_good_jobs_on_concurrency_key_when_unfinished", where: "(finished_at IS NULL)" + t.index ["created_at"], name: "index_good_jobs_on_created_at" t.index ["cron_key", "created_at"], name: "index_good_jobs_on_cron_key_and_created_at_cond", where: "(cron_key IS NOT NULL)" - t.index ["cron_key", "cron_at"], name: "index_good_jobs_on_cron_key_and_cron_at_cond", unique: true, where: "(cron_key IS NOT NULL)" - t.index ["finished_at"], name: "index_good_jobs_jobs_on_finished_at", where: "((retried_good_job_id IS NULL) AND (finished_at IS NOT NULL))" + t.index ["cron_key", "cron_at"], name: "index_good_jobs_on_cron_key_and_cron_at_cond", unique: true, order: { cron_at: "DESC NULLS LAST" }, where: "(cron_key IS NOT NULL)" + t.index ["finished_at"], name: "index_good_jobs_jobs_on_finished_at_only", where: "(finished_at IS NOT NULL)" + t.index ["finished_at"], name: "index_good_jobs_on_discarded", order: :desc, where: "((finished_at IS NOT NULL) AND (error IS NOT NULL))" t.index ["finished_at"], name: "index_good_jobs_on_finished_at" + t.index ["id"], name: "index_good_jobs_on_unfinished_or_errored", where: "((finished_at IS NULL) OR (error IS NOT NULL))" + t.index ["job_class", "finished_at"], name: "index_good_jobs_on_discarded_job_class", where: "((finished_at IS NOT NULL) AND (error IS NOT NULL))" + t.index ["job_class"], name: "index_good_jobs_on_job_class" t.index ["labels"], name: "index_good_jobs_on_labels", where: "(labels IS NOT NULL)", using: :gin t.index ["locked_by_id"], name: "index_good_jobs_on_locked_by_id", where: "(locked_by_id IS NOT NULL)" t.index ["priority", "created_at"], name: "index_good_job_jobs_for_candidate_lookup", where: "(finished_at IS NULL)" - t.index ["priority", "created_at"], name: "index_good_jobs_jobs_on_priority_created_at_when_unfinished", order: { priority: "DESC NULLS LAST" }, where: "(finished_at IS NULL)" - t.index ["priority", "scheduled_at"], name: "index_good_jobs_on_priority_scheduled_at_unfinished_unlocked", where: "((finished_at IS NULL) AND (locked_by_id IS NULL))" - t.index ["queue_name", "scheduled_at"], name: "index_good_jobs_on_queue_name_and_scheduled_at", where: "(finished_at IS NULL)" + t.index ["priority", "scheduled_at", "id"], name: "index_good_jobs_for_candidate_dequeue_unlocked", where: "((finished_at IS NULL) AND (locked_by_id IS NULL))" + t.index ["priority", "scheduled_at", "id"], name: "index_good_jobs_on_priority_scheduled_at_unfinished", where: "(finished_at IS NULL)" + t.index ["queue_name", "priority", "created_at"], name: "index_good_jobs_dequeue_by_queue", where: "((finished_at IS NULL) AND (locked_by_id IS NULL))" + t.index ["queue_name", "priority", "scheduled_at"], name: "index_good_jobs_dequeue_by_queue_scheduled_at", where: "((finished_at IS NULL) AND (locked_by_id IS NULL))" + t.index ["queue_name", "scheduled_at", "id"], name: "index_good_jobs_on_queue_name_priority_scheduled_at_unfinished", where: "(finished_at IS NULL)" + t.index ["queue_name"], name: "index_good_jobs_on_queue_name" + t.index ["scheduled_at", "queue_name"], name: "index_good_jobs_on_scheduled_at_and_queue_name" t.index ["scheduled_at"], name: "index_good_jobs_on_scheduled_at", where: "(finished_at IS NULL)" end - create_table "imports", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.integer "kind" - t.uuid "language_id", null: false + create_table "imports", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "number_of_lines" t.jsonb "processing_errors" + t.integer "kind" t.integer "status", default: 0 t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.uuid "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "language_id", null: false t.index ["language_id"], name: "index_imports_on_language_id" t.index ["university_id"], name: "index_imports_on_university_id" t.index ["user_id"], name: "index_imports_on_user_id" end - create_table "languages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.string "iso_code" + create_table "languages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name" - t.string "summernote_locale" + t.string "iso_code" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "summernote_locale" end create_table "languages_universities", id: false, force: :cascade do |t| @@ -2036,44 +2063,44 @@ t.index ["university_id", "language_id"], name: "index_languages_universities_on_university_id_and_language_id" end - create_table "research_hal_authors", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false + create_table "research_hal_authors", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "docid" - t.string "first_name" t.string "form_identifier" - t.string "full_name" - t.string "last_name" t.string "person_identifier" + t.string "first_name" + t.string "last_name" + t.string "full_name" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["docid"], name: "index_research_hal_authors_on_docid" end create_table "research_hal_authors_publications", id: false, force: :cascade do |t| - t.uuid "research_hal_author_id", null: false t.uuid "research_publication_id", null: false + t.uuid "research_hal_author_id", null: false t.index ["research_hal_author_id", "research_publication_id"], name: "hal_publication_author" t.index ["research_publication_id", "research_hal_author_id"], name: "hal_author_publication" end create_table "research_hal_authors_university_people", id: false, force: :cascade do |t| - t.uuid "research_hal_author_id", null: false t.uuid "university_person_id", null: false + t.uuid "research_hal_author_id", null: false t.index ["research_hal_author_id", "university_person_id"], name: "hal_person_author" t.index ["university_person_id", "research_hal_author_id"], name: "hal_author_person" end create_table "research_journal_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.string "issn" - t.uuid "language_id" t.text "meta_description" - t.string "slug" t.text "summary" t.string "title" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "slug" + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_c2c2f792ff", unique: true t.index ["about_id"], name: "index_research_journal_localizations_on_about_id" t.index ["language_id"], name: "index_research_journal_localizations_on_language_id" @@ -2081,67 +2108,67 @@ end create_table "research_journal_paper_kind_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "language_id" t.string "slug" t.string "title" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_ab294e2ab8", unique: true t.index ["about_id"], name: "index_research_journal_paper_kind_localizations_on_about_id" t.index ["language_id"], name: "index_research_journal_paper_kind_localizations_on_language_id" t.index ["university_id"], name: "idx_on_university_id_dc9f1267b7" end - create_table "research_journal_paper_kinds", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "journal_id", null: false + create_table "research_journal_paper_kinds", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false + t.uuid "journal_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["journal_id"], name: "index_research_journal_paper_kinds_on_journal_id" t.index ["university_id"], name: "index_research_journal_paper_kinds_on_university_id" end create_table "research_journal_paper_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.string "abstract" t.text "authors_list" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.text "keywords" - t.uuid "language_id" t.text "meta_description" t.boolean "published", default: false t.datetime "published_at" t.string "slug" t.text "summary" t.string "title" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_6a26cfcece", unique: true t.index ["about_id"], name: "index_research_journal_paper_localizations_on_about_id" t.index ["language_id"], name: "index_research_journal_paper_localizations_on_language_id" t.index ["university_id"], name: "index_research_journal_paper_localizations_on_university_id" end - create_table "research_journal_papers", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.date "accepted_at" - t.text "bibliography" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.string "doi" - t.uuid "kind_id" - t.integer "position", null: false - t.date "received_at" + create_table "research_journal_papers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "research_journal_id", null: false t.uuid "research_journal_volume_id" - t.text "text" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.uuid "updated_by_id" + t.text "bibliography" + t.integer "position", null: false + t.text "text" + t.uuid "kind_id" + t.date "received_at" + t.date "accepted_at" + t.string "doi" + t.datetime "deleted_at" t.index ["kind_id"], name: "index_research_journal_papers_on_kind_id" t.index ["research_journal_id"], name: "index_research_journal_papers_on_research_journal_id" t.index ["research_journal_volume_id"], name: "index_research_journal_papers_on_research_journal_volume_id" @@ -2150,21 +2177,16 @@ end create_table "research_journal_papers_researchers", force: :cascade do |t| - t.uuid "paper_id", null: false t.uuid "researcher_id", null: false + t.uuid "paper_id", null: false t.index ["paper_id"], name: "index_research_journal_papers_researchers_on_paper_id" t.index ["researcher_id"], name: "index_research_journal_papers_researchers_on_researcher_id" end create_table "research_journal_volume_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" t.string "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" t.text "keywords" - t.uuid "language_id" t.text "meta_description" t.boolean "published", default: false t.datetime "published_at" @@ -2172,8 +2194,13 @@ t.text "summary" t.text "text" t.string "title" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_adf437eb06", unique: true t.index ["about_id"], name: "index_research_journal_volume_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_2ac8ff2d6b" @@ -2181,66 +2208,66 @@ t.index ["university_id"], name: "index_research_journal_volume_localizations_on_university_id" end - create_table "research_journal_volumes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.integer "number" - t.uuid "research_journal_id", null: false + create_table "research_journal_volumes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false + t.uuid "research_journal_id", null: false + t.integer "number" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["research_journal_id"], name: "index_research_journal_volumes_on_research_journal_id" t.index ["university_id"], name: "index_research_journal_volumes_on_university_id" end - create_table "research_journals", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" + create_table "research_journals", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["university_id"], name: "index_research_journals_on_university_id" end - create_table "research_laboratories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_laboratories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.string "address" + t.string "zipcode" t.string "city" t.string "country" t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "university_id", null: false t.datetime "updated_at", null: false - t.string "zipcode" + t.datetime "deleted_at" t.index ["university_id"], name: "index_research_laboratories_on_university_id" end create_table "research_laboratories_university_people", id: false, force: :cascade do |t| - t.uuid "research_laboratory_id", null: false t.uuid "university_person_id", null: false + t.uuid "research_laboratory_id", null: false t.index ["research_laboratory_id", "university_person_id"], name: "person_laboratory" t.index ["university_person_id", "research_laboratory_id"], name: "laboratory_person" end - create_table "research_laboratory_axes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.integer "position", null: false - t.uuid "research_laboratory_id", null: false + create_table "research_laboratory_axes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false + t.uuid "research_laboratory_id", null: false + t.integer "position", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["research_laboratory_id"], name: "index_research_laboratory_axes_on_research_laboratory_id" t.index ["university_id"], name: "index_research_laboratory_axes_on_university_id" end create_table "research_laboratory_axis_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "language_id" t.text "meta_description" t.string "name" t.string "short_name" t.text "summary" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_3895cd52f3", unique: true t.index ["about_id"], name: "index_research_laboratory_axis_localizations_on_about_id" t.index ["language_id"], name: "index_research_laboratory_axis_localizations_on_language_id" @@ -2248,67 +2275,67 @@ end create_table "research_laboratory_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.string "address_additional" t.string "address_name" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "language_id" t.string "name" - t.string "slug" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "slug" + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_a3deee8fec", unique: true t.index ["about_id"], name: "index_research_laboratory_localizations_on_about_id" t.index ["language_id"], name: "index_research_laboratory_localizations_on_language_id" t.index ["university_id"], name: "index_research_laboratory_localizations_on_university_id" end - create_table "research_publications", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.text "abstract" - t.text "anr_project_references", default: [], array: true - t.json "authors_citeproc" - t.text "authors_list" - t.text "citation_full" - t.datetime "created_at", null: false - t.jsonb "data" - t.string "docsubtype" - t.string "doctype" - t.string "doi" - t.text "file" + create_table "research_publications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "hal_docid" + t.jsonb "data" + t.string "title" + t.string "url" + t.string "ref" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "hal_url" - t.string "journal_title" - t.boolean "open_access" t.date "publication_date" - t.string "ref" + t.string "doi" t.string "slug" + t.text "citation_full" + t.boolean "open_access" + t.text "abstract" + t.string "journal_title" + t.text "file" + t.text "authors_list" + t.json "authors_citeproc" t.integer "source", default: 0 - t.string "title" - t.datetime "updated_at", null: false - t.string "url" + t.text "anr_project_references", default: [], array: true + t.string "doctype" + t.string "docsubtype" t.index ["hal_docid"], name: "index_research_publications_on_hal_docid" t.index ["slug"], name: "index_research_publications_on_slug" end create_table "research_publications_university_people", id: false, force: :cascade do |t| - t.uuid "research_publication_id", null: false t.uuid "university_person_id", null: false + t.uuid "research_publication_id", null: false t.index ["research_publication_id", "university_person_id"], name: "index_person_publication" t.index ["university_person_id", "research_publication_id"], name: "index_publication_person" end - create_table "research_theses", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_theses", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "research_laboratory_id", null: false t.uuid "author_id", null: false + t.uuid "director_id", null: false + t.date "started_at" t.boolean "completed", default: false t.date "completed_at" t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "director_id", null: false - t.uuid "research_laboratory_id", null: false - t.date "started_at" - t.uuid "university_id", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["author_id"], name: "index_research_theses_on_author_id" t.index ["director_id"], name: "index_research_theses_on_director_id" t.index ["research_laboratory_id"], name: "index_research_theses_on_research_laboratory_id" @@ -2316,14 +2343,14 @@ end create_table "research_thesis_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.text "abstract" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.uuid "language_id" t.string "title" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_f1054bd8a7", unique: true t.index ["about_id"], name: "index_research_thesis_localizations_on_about_id" t.index ["language_id"], name: "index_research_thesis_localizations_on_language_id" @@ -2331,18 +2358,18 @@ end create_table "search_index", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_localization_id", null: false - t.string "about_localization_type", null: false - t.uuid "about_object_id", null: false + t.uuid "university_id", null: false + t.string "title" + t.text "text" + t.uuid "language_id", null: false t.string "about_object_type", null: false - t.datetime "created_at", null: false + t.uuid "about_object_id", null: false + t.string "about_localization_type", null: false + t.uuid "about_localization_id", null: false + t.uuid "website_id" t.uuid "extranet_id" - t.uuid "language_id", null: false - t.text "text" - t.string "title" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.uuid "website_id" t.index ["about_localization_type", "about_localization_id"], name: "index_search_on_about_localization" t.index ["about_object_type", "about_object_id"], name: "index_search_on_about_object" t.index ["extranet_id"], name: "index_search_index_on_extranet_id" @@ -2351,27 +2378,27 @@ t.index ["website_id"], name: "index_search_index_on_website_id" end - create_table "server_emergency_messages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.text "content_en" - t.text "content_fr" - t.datetime "created_at", null: false - t.datetime "delivered_at" - t.integer "delivered_count" + create_table "server_emergency_messages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id" t.string "name" t.string "role" - t.string "subject_en" t.string "subject_fr" - t.uuid "university_id" + t.string "subject_en" + t.text "content_fr" + t.text "content_en" + t.datetime "delivered_at" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "delivered_count" t.index ["university_id"], name: "index_server_emergency_messages_on_university_id", where: "(university_id IS NOT NULL)" end create_table "server_evolution_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false t.uuid "evolution_id", null: false t.uuid "language_id", null: false - t.text "text" t.string "title" + t.text "text" + t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["evolution_id", "language_id"], name: "idx_on_evolution_id_language_id_7cb24cbc2b", unique: true t.index ["evolution_id"], name: "index_server_evolution_localizations_on_evolution_id" @@ -2379,112 +2406,112 @@ end create_table "server_evolutions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false t.date "released_at" + t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "server_tasks_counts", force: :cascade do |t| - t.datetime "created_at", null: false t.integer "tasks_pending", default: 0, null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "universities", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "universities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name" + t.string "identifier" t.string "address" - t.boolean "admin_already_auto_promoted", default: false + t.string "zipcode" t.string "city" - t.float "contribution_amount" t.string "country" + t.boolean "private" t.datetime "created_at", null: false - t.string "default_github_access_token" - t.uuid "default_language_id", null: false - t.boolean "has_sso", default: false - t.string "identifier" + t.datetime "updated_at", null: false + t.string "mail_from_name" + t.string "mail_from_address" t.date "invoice_date" t.integer "invoice_date_yday" - t.boolean "is_really_a_university", default: true - t.string "mail_from_address" - t.string "mail_from_name" - t.string "name" - t.boolean "private" - t.string "sso_button_label" - t.text "sso_cert" - t.jsonb "sso_mapping" - t.string "sso_name_identifier_format" + t.boolean "has_sso", default: false t.integer "sso_provider", default: 0 t.string "sso_target_url" - t.datetime "updated_at", null: false - t.string "zipcode" + t.text "sso_cert" + t.string "sso_name_identifier_format" + t.jsonb "sso_mapping" + t.string "sso_button_label" + t.uuid "default_language_id", null: false + t.boolean "is_really_a_university", default: true + t.float "contribution_amount" + t.string "default_github_access_token" + t.boolean "admin_already_auto_promoted", default: false t.index ["default_language_id"], name: "index_universities_on_default_language_id" t.index ["name"], name: "index_universities_on_name", opclass: :gin_trgm_ops, using: :gin end - create_table "university_apps", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false + create_table "university_apps", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name" - t.string "token" - t.boolean "token_was_displayed", default: false t.uuid "university_id", null: false + t.string "token" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "token_was_displayed", default: false t.index ["token"], name: "index_university_apps_on_token", unique: true t.index ["university_id"], name: "index_university_apps_on_university_id" end create_table "university_file_servers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.string "ftp_host" - t.string "ftp_password" - t.string "ftp_path" + t.string "url" t.integer "ftp_port" t.string "ftp_username" + t.string "ftp_password" + t.string "ftp_path" + t.string "ftp_host" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "url" t.index ["university_id"], name: "index_university_file_servers_on_university_id", unique: true end - create_table "university_organization_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + create_table "university_organization_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.datetime "created_at", null: false - t.boolean "is_taxonomy", default: false - t.string "migration_identifier" + t.datetime "updated_at", null: false t.uuid "parent_id" t.integer "position", null: false + t.boolean "is_taxonomy", default: false + t.string "migration_identifier" + t.string "bodyclass" t.integer "position_in_tree" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.index ["parent_id"], name: "index_university_organization_categories_on_parent_id" t.index ["university_id"], name: "index_university_organization_categories_on_university_id" end - create_table "university_organization_categories_organizations", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "category_id", null: false + create_table "university_organization_categories_organizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "organization_id", null: false + t.uuid "category_id", null: false t.index ["category_id"], name: "idx_on_category_id_7494b991ff" t.index ["organization_id"], name: "idx_on_organization_id_7e5c9e451b" end create_table "university_organization_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name" + t.string "slug" t.uuid "about_id" - t.string "breadcrumb_title" + t.uuid "language_id" + t.uuid "university_id" t.datetime "created_at", null: false - t.text "featured_image_credit" + t.datetime "updated_at", null: false t.text "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" + t.text "meta_description" + t.text "summary" + t.string "migration_identifier" + t.string "subtitle" + t.string "breadcrumb_title" t.boolean "header_cta", default: false t.string "header_cta_label" t.string "header_cta_url" t.text "header_text" - t.uuid "language_id" - t.text "meta_description" - t.string "migration_identifier" - t.string "name" - t.string "slug" - t.string "subtitle" - t.text "summary" - t.uuid "university_id" - t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_a3c481c2fd", unique: true t.index ["about_id"], name: "idx_on_about_id_f5fce0a0b7" t.index ["featured_media_id"], name: "idx_on_featured_media_id_41b368667a" @@ -2494,30 +2521,30 @@ end create_table "university_organization_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.string "address_additional" t.string "address_name" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" - t.string "featured_media_alt" - t.uuid "featured_media_id" - t.uuid "language_id" t.string "linkedin" t.string "long_name" t.string "mastodon" t.text "meta_description" - t.string "migration_identifier" t.string "name" - t.boolean "published", default: true - t.datetime "published_at" t.string "slug" t.text "summary" t.text "text" t.string "twitter" + t.string "url" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "url" + t.string "featured_media_alt" + t.text "featured_image_credit" + t.string "migration_identifier" + t.boolean "published", default: true + t.datetime "published_at" + t.datetime "deleted_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_eb921fd47b", unique: true t.index ["about_id"], name: "index_university_organization_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_e0a6e6cb52" @@ -2525,107 +2552,107 @@ t.index ["university_id"], name: "index_university_organization_localizations_on_university_id" end - create_table "university_organizations", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "university_organizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.string "address" - t.string "bodyclass" + t.string "zipcode" t.string "city" t.string "country" - t.datetime "created_at", null: false - t.uuid "created_by_id" - t.datetime "deleted_at" + t.string "phone" t.string "email" + t.string "siren" t.integer "kind", default: 10 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "nic" t.float "latitude" t.float "longitude" t.string "migration_identifier" - t.string "nic" - t.string "phone" - t.string "siren" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false - t.string "zipcode" + t.uuid "created_by_id" + t.string "bodyclass" + t.datetime "deleted_at" t.index ["created_by_id"], name: "index_university_organizations_on_created_by_id" t.index ["university_id"], name: "index_university_organizations_on_university_id" end - create_table "university_people", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "address" - t.integer "address_visibility", default: 0 - t.date "birthdate" - t.string "bodyclass" - t.string "city" - t.string "country" + create_table "university_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "user_id" + t.boolean "is_researcher" + t.boolean "is_teacher" + t.boolean "is_administration" t.datetime "created_at", null: false - t.uuid "created_by_id" - t.datetime "deleted_at" + t.datetime "updated_at", null: false + t.string "phone_mobile" t.string "email" - t.integer "email_visibility", default: 0 - t.integer "gender" t.boolean "habilitation", default: false - t.datetime "invitation_sent_at" - t.boolean "is_administration" + t.boolean "tenure", default: false t.boolean "is_alumnus", default: false t.boolean "is_author" - t.boolean "is_researcher" - t.boolean "is_teacher" + t.integer "gender" + t.date "birthdate" + t.string "phone_professional" + t.string "phone_personal" + t.string "address" + t.string "zipcode" + t.string "city" + t.string "country" + t.integer "address_visibility", default: 0 t.integer "linkedin_visibility", default: 0 + t.integer "twitter_visibility", default: 0 t.integer "mastodon_visibility", default: 0 - t.string "phone_mobile" t.integer "phone_mobile_visibility", default: 0 - t.string "phone_personal" - t.integer "phone_personal_visibility", default: 0 - t.string "phone_professional" t.integer "phone_professional_visibility", default: 0 - t.boolean "tenure", default: false - t.integer "twitter_visibility", default: 0 - t.uuid "university_id", null: false - t.datetime "updated_at", null: false - t.uuid "user_id" - t.string "zipcode" + t.integer "phone_personal_visibility", default: 0 + t.integer "email_visibility", default: 0 + t.uuid "created_by_id" + t.string "bodyclass" + t.datetime "deleted_at" + t.datetime "invitation_sent_at" t.index ["created_by_id"], name: "index_university_people_on_created_by_id" t.index ["university_id"], name: "index_university_people_on_university_id" t.index ["user_id"], name: "index_university_people_on_user_id" end - create_table "university_people_person_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "category_id", null: false + create_table "university_people_person_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "person_id", null: false + t.uuid "category_id", null: false t.index ["category_id"], name: "index_university_people_person_categories_on_category_id" t.index ["person_id"], name: "index_university_people_person_categories_on_person_id" end - create_table "university_person_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.string "bodyclass" + create_table "university_person_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.datetime "created_at", null: false - t.boolean "is_taxonomy", default: false + t.datetime "updated_at", null: false t.uuid "parent_id" t.integer "position", null: false + t.boolean "is_taxonomy", default: false + t.string "bodyclass" t.integer "position_in_tree" - t.uuid "university_id", null: false - t.datetime "updated_at", null: false t.index ["parent_id"], name: "index_university_person_categories_on_parent_id" t.index ["university_id"], name: "index_university_person_categories_on_university_id" end create_table "university_person_category_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "name" + t.string "slug" t.uuid "about_id" - t.string "breadcrumb_title" + t.uuid "language_id" + t.uuid "university_id" t.datetime "created_at", null: false - t.text "featured_image_credit" + t.datetime "updated_at", null: false t.text "featured_media_alt" - t.uuid "featured_media_id" + t.text "featured_image_credit" + t.text "meta_description" + t.text "summary" + t.string "subtitle" + t.string "breadcrumb_title" t.boolean "header_cta", default: false t.string "header_cta_label" t.string "header_cta_url" t.text "header_text" - t.uuid "language_id" - t.text "meta_description" - t.string "name" - t.string "slug" - t.string "subtitle" - t.text "summary" - t.uuid "university_id" - t.datetime "updated_at", null: false + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_6784c3101c", unique: true t.index ["about_id"], name: "index_university_person_category_localizations_on_about_id" t.index ["featured_media_id"], name: "idx_on_featured_media_id_a6d0442b45" @@ -2635,86 +2662,86 @@ end create_table "university_person_experience_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.string "description" + t.uuid "about_id" t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_6610a91469", unique: true t.index ["about_id"], name: "index_university_person_experience_localizations_on_about_id" t.index ["language_id"], name: "idx_on_language_id_61a5fb5403" t.index ["university_id"], name: "idx_on_university_id_1be9c668d5" end - create_table "university_person_experiences", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.integer "from_year" - t.uuid "organization_id", null: false + create_table "university_person_experiences", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "person_id", null: false + t.uuid "organization_id", null: false + t.integer "from_year" t.integer "to_year" - t.uuid "university_id", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["organization_id"], name: "index_university_person_experiences_on_organization_id" t.index ["person_id"], name: "index_university_person_experiences_on_person_id" t.index ["university_id"], name: "index_university_person_experiences_on_university_id" end create_table "university_person_involvement_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.string "description" + t.uuid "about_id" t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_5991ad3c2d", unique: true t.index ["about_id"], name: "index_university_person_involvement_localizations_on_about_id" t.index ["language_id"], name: "idx_on_language_id_75d7367448" t.index ["university_id"], name: "idx_on_university_id_0b815cf13a" end - create_table "university_person_involvements", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.integer "kind" + create_table "university_person_involvements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.uuid "person_id", null: false - t.integer "position", null: false - t.uuid "target_id", null: false + t.integer "kind" t.string "target_type", null: false - t.uuid "university_id", null: false + t.uuid "target_id", null: false + t.integer "position", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["person_id"], name: "index_university_person_involvements_on_person_id" t.index ["target_type", "target_id"], name: "index_university_person_involvements_on_target" t.index ["university_id"], name: "index_university_person_involvements_on_university_id" end create_table "university_person_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" t.text "biography" - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.text "featured_image_credit" - t.text "featured_media_alt" - t.uuid "featured_media_id" t.string "first_name" - t.uuid "language_id" t.string "last_name" t.string "linkedin" t.string "mastodon" t.text "meta_description" t.string "name" t.text "picture_credit" - t.boolean "published", default: true - t.datetime "published_at" t.string "slug" t.text "summary" t.string "twitter" + t.string "url" + t.uuid "about_id" + t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "url" + t.text "featured_media_alt" + t.text "featured_image_credit" + t.datetime "deleted_at" + t.boolean "published", default: true + t.datetime "published_at" + t.uuid "featured_media_id" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_54757d0dad", unique: true t.index ["about_id"], name: "index_university_person_localizations_on_about_id" t.index ["featured_media_id"], name: "index_university_person_localizations_on_featured_media_id" @@ -2724,79 +2751,79 @@ end create_table "university_role_localizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id" - t.datetime "created_at", null: false - t.datetime "deleted_at" t.string "description" + t.uuid "about_id" t.uuid "language_id" t.uuid "university_id" + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["about_id", "language_id"], name: "idx_on_about_id_language_id_90a71d885a", unique: true t.index ["about_id"], name: "index_university_role_localizations_on_about_id" t.index ["language_id"], name: "index_university_role_localizations_on_language_id" t.index ["university_id"], name: "index_university_role_localizations_on_university_id" end - create_table "university_roles", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.datetime "created_at", null: false - t.datetime "deleted_at" - t.integer "position", null: false - t.uuid "target_id" - t.string "target_type" + create_table "university_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false + t.string "target_type" + t.uuid "target_id" + t.integer "position", null: false + t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.datetime "deleted_at" t.index ["target_type", "target_id"], name: "index_university_roles_on_target" t.index ["university_id"], name: "index_university_roles_on_university_id" end - create_table "user_favorites", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.uuid "about_id", null: false + create_table "user_favorites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "user_id", null: false t.string "about_type", null: false + t.uuid "about_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.uuid "user_id", null: false t.index ["about_type", "about_id"], name: "index_user_favorites_on_about" t.index ["user_id"], name: "index_user_favorites_on_user_id" end - create_table "users", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| - t.integer "brevo_contact_id" - t.datetime "confirmation_sent_at", precision: nil - t.string "confirmation_token" - t.datetime "confirmed_at", precision: nil - t.datetime "created_at", null: false - t.datetime "current_sign_in_at", precision: nil - t.string "current_sign_in_ip" - t.string "direct_otp" - t.string "direct_otp_delivery_method" - t.datetime "direct_otp_sent_at", precision: nil - t.string "email", default: "", null: false - t.string "encrypted_otp_secret_key" - t.string "encrypted_otp_secret_key_iv" - t.string "encrypted_otp_secret_key_salt" - t.string "encrypted_password", default: "", null: false - t.integer "failed_attempts", default: 0, null: false + create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false t.string "first_name" - t.uuid "language_id" t.string "last_name" + t.integer "role", default: 0 + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at", precision: nil + t.datetime "remember_created_at", precision: nil + t.integer "sign_in_count", default: 0, null: false + t.datetime "current_sign_in_at", precision: nil t.datetime "last_sign_in_at", precision: nil + t.string "current_sign_in_ip" t.string "last_sign_in_ip" + t.string "confirmation_token" + t.datetime "confirmed_at", precision: nil + t.datetime "confirmation_sent_at", precision: nil + t.string "unconfirmed_email" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" t.datetime "locked_at", precision: nil + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "language_id" t.string "mobile_phone" - t.boolean "optin_newsletter" - t.string "picture_url" - t.datetime "remember_created_at", precision: nil - t.datetime "reset_password_sent_at", precision: nil - t.string "reset_password_token" - t.integer "role", default: 0 t.integer "second_factor_attempts_count", default: 0 - t.string "session_token" - t.integer "sign_in_count", default: 0, null: false + t.string "encrypted_otp_secret_key" + t.string "encrypted_otp_secret_key_iv" + t.string "encrypted_otp_secret_key_salt" + t.string "direct_otp" + t.datetime "direct_otp_sent_at", precision: nil t.datetime "totp_timestamp", precision: nil - t.string "unconfirmed_email" - t.uuid "university_id", null: false - t.string "unlock_token" - t.datetime "updated_at", null: false + t.string "session_token" + t.string "picture_url" + t.string "direct_otp_delivery_method" + t.boolean "optin_newsletter" + t.integer "brevo_contact_id" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email", "university_id"], name: "index_users_on_email_and_university_id", unique: true t.index ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true From 299a50b7f6e98112a3cfb55c29f3441170ba8775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= Date: Mon, 19 Oct 2026 12:00:42 +0200 Subject: [PATCH 2/2] fix --- app/jobs/application_job.rb | 2 +- app/jobs/communication/website/git_file/generate_content_job.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index 849adca682..dc5bafaccc 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -20,7 +20,7 @@ class ApplicationJob < ActiveJob::Base # invoked in the context of the job instance (see "Dynamic labels" below). # The rule only applies to jobs that were enqueued with this label in # `good_job_labels`. - label: -> { "#{self.class.name}-#{queue_name}-#{digest_arguments(arguments)}" } + label: -> { "#{self.class.name}-#{queue_name}-#{digest_arguments(arguments)}" }, # Apply the rule's label to every job of this class (and its subclasses), # so the jobs don't need to be enqueued with it. Defaults to false. diff --git a/app/jobs/communication/website/git_file/generate_content_job.rb b/app/jobs/communication/website/git_file/generate_content_job.rb index d590b4c7ce..71eed6d253 100644 --- a/app/jobs/communication/website/git_file/generate_content_job.rb +++ b/app/jobs/communication/website/git_file/generate_content_job.rb @@ -2,9 +2,9 @@ class Communication::Website::GitFile::GenerateContentJob < ApplicationJob queue_as :cats good_job_concurrency_rule( + label: -> { "#{self.class.name}-#{queue_name}-#{arguments.first.to_global_id}" }, enqueue_limit: 1, perform_limit: 1, - label: -> { "#{self.class.name}-#{queue_name}-#{arguments.first.to_global_id}" } ) def perform(git_file)