diff --git a/back/.rubocop_todo.yml b/back/.rubocop_todo.yml index 3b36fe322e06..b32f74823131 100644 --- a/back/.rubocop_todo.yml +++ b/back/.rubocop_todo.yml @@ -201,6 +201,7 @@ RSpec/DescribeClass: - 'spec/tasks/single_use/migrate_homepage_craftjson_task_spec.ignore.rb' - 'spec/tasks/single_use/rename_gv_profile_spec.ignore.rb' - 'spec/tasks/single_use/substitute_cl_gv_task_spec.ignore.rb' + - 'spec/tasks/single_use/custom_field_orderings_spec.ignore.rb' # Offense count: 149 # This cop supports safe autocorrection (--autocorrect). @@ -337,6 +338,7 @@ RSpec/SpecFilePathSuffix: - 'spec/tasks/single_use/move_ideation_custom_forms_to_project_spec.ignore.rb' - 'spec/tasks/single_use/rename_gv_profile_spec.ignore.rb' - 'spec/tasks/single_use/substitute_cl_gv_task_spec.ignore.rb' + - 'spec/tasks/single_use/custom_field_orderings_spec.ignore.rb' # Offense count: 77 RSpec/StubbedMock: diff --git a/back/lib/tasks/single_use/20251103_custom_fields_orderings.rake b/back/lib/tasks/single_use/20251103_custom_fields_orderings.rake new file mode 100644 index 000000000000..53a966c834e4 --- /dev/null +++ b/back/lib/tasks/single_use/20251103_custom_fields_orderings.rake @@ -0,0 +1,51 @@ +namespace :fix_existing_tenants do + desc 'Fix custom fields orderings and make sure the first field is a page.' + task :custom_fields_orderings, [] => [:environment] do + reporter = ScriptReporter.new + Tenant.all.each do |tenant| + tenant.switch do + # rubocop:disable Performance/CollectionLiteralInLoop + ([nil] + CustomForm.all).each do |form| + fields = CustomField.where(resource_id: form&.id).order(:ordering) + + # Check if ordering is correct + next if fields.pluck(:ordering) == (0...fields.size).to_a + + # Fix orderings + fields.each.with_index do |field, index| + field.update_column(:ordering, index) + end + reporter.add_change( + nil, + 'Fixed orderings', + context: { tenant: tenant.host, form: form&.id } + ) + + # First field must be a page + next if !form + + fields = CustomField.where(resource_id: form.id).order(:ordering) + next if fields.first.page? + + first_page = fields.find(&:page?) + if !first_page + reporter.add_error( + 'Form has no pages!', + context: { tenant: tenant.host, form: form.id } + ) + next + end + + first_page.move_to_top + reporter.add_change( + nil, + 'Page moved to top', + context: { tenant: tenant.host, form: form.id, page: first_page.id } + ) + end + # rubocop:enable Performance/CollectionLiteralInLoop + end + end + reporter.report!('fix_custom_fields_orderings_report.json', verbose: true) + end +end diff --git a/back/spec/tasks/single_use/custom_field_orderings_spec.ignore.rb b/back/spec/tasks/single_use/custom_field_orderings_spec.ignore.rb new file mode 100644 index 000000000000..d3108f760797 --- /dev/null +++ b/back/spec/tasks/single_use/custom_field_orderings_spec.ignore.rb @@ -0,0 +1,45 @@ +require 'rails_helper' + +describe 'fix_existing_tenants:custom_fields_orderings rake task' do + before { load_rake_tasks_if_not_loaded } + + it 'Fixes the orderings' do + form1 = create(:custom_form) + create(:custom_field, resource: form1, input_type: 'number', key: 'field2') + create(:custom_field_page, resource: form1, key: 'field1').update_column(:ordering, 0) + create(:custom_field, resource: form1, input_type: 'number', key: 'field3').update_column(:ordering, 3) + create(:custom_field, resource: form1, input_type: 'text', key: 'field4').update_column(:ordering, 3) + create(:custom_field_page, resource: form1, key: 'field5').update_column(:ordering, 4) + + form2 = create(:custom_form) + create(:custom_field_page, resource: form2, key: 'field1') + create(:custom_field, resource: form2, input_type: 'number', key: 'field2') + create(:custom_field, resource: form2, input_type: 'text', key: 'field3') + create(:custom_field_page, resource: form2, key: 'field4') + + create(:custom_field, resource_id: nil, resource_type: 'User', input_type: 'text', key: 'field1') + create(:custom_field, resource_id: nil, resource_type: 'User', input_type: 'number', key: 'field2').update_column(:ordering, 2) + + Rake::Task['fix_existing_tenants:custom_fields_orderings'].invoke + + expect(form1.reload.custom_fields.pluck(:key, :ordering)).to eq([ + ['field1', 0], + ['field2', 1], + ['field3', 2], + ['field4', 3], + ['field5', 4] + ]) + + expect(form2.reload.custom_fields.pluck(:key, :ordering)).to eq([ + ['field1', 0], + ['field2', 1], + ['field3', 2], + ['field4', 3] + ]) + + expect(CustomField.where(resource_id: nil).order(:ordering).pluck(:key, :ordering)).to eq([ + ['field1', 0], + ['field2', 1] + ]) + end +end