From b99660f5875f38342ad36072fc5412e4e488cab5 Mon Sep 17 00:00:00 2001 From: as-op Date: Wed, 21 Oct 2026 15:17:50 +0200 Subject: [PATCH 1/2] [JIM-261] Custom field values are silently dropped when a type's form configuration changes in the same request or job https://community.openproject.org/wp/JIM-261 --- app/models/form_configuration.rb | 1 + app/models/work_package.rb | 7 +++- .../work_package_custom_fields_spec.rb | 9 +++++ ...ct_work_packages_job_custom_fields_spec.rb | 38 +++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/app/models/form_configuration.rb b/app/models/form_configuration.rb index eaf563791ab0..017d191bfcd3 100644 --- a/app/models/form_configuration.rb +++ b/app/models/form_configuration.rb @@ -114,6 +114,7 @@ def persist_staged_attribute_groups return unless groups attribute_group_rows.store(groups) + WorkPackage.clear_available_custom_fields_cache remove_instance_variable(:@stored_attribute_groups) if defined?(@stored_attribute_groups) end diff --git a/app/models/work_package.rb b/app/models/work_package.rb index 39a069a9fb8d..72b940ec2746 100644 --- a/app/models/work_package.rb +++ b/app/models/work_package.rb @@ -49,6 +49,7 @@ class WorkPackage < ApplicationRecord include OpenProject::Journal::AttachmentHelper + AVAILABLE_CUSTOM_FIELDS_CACHE_PREFIX = "work_package_custom_fields_" DONE_RATIO_OPTIONS = %w[field status].freeze TOTAL_PERCENT_COMPLETE_MODE_OPTIONS = %w[work_weighted_average simple_average].freeze @@ -505,6 +506,10 @@ def self.available_custom_fields(work_package) end end + def self.clear_available_custom_fields_cache + RequestStore.store.delete_if { |key, _| key.to_s.start_with?(AVAILABLE_CUSTOM_FIELDS_CACHE_PREFIX) } + end + def self.preload_available_custom_fields(work_packages) type_variant_ids = type_variant_ids_by_pair(work_packages) @@ -591,7 +596,7 @@ def self.form_configuration_custom_fields_join(variant_ids) private_class_method :form_configuration_custom_fields_join def self.available_custom_field_key(work_package) - :"work_package_custom_fields_#{work_package.project_id}_#{work_package.type_id}" + :"#{AVAILABLE_CUSTOM_FIELDS_CACHE_PREFIX}#{work_package.project_id}_#{work_package.type_id}" end private_class_method :available_custom_field_key diff --git a/spec/models/work_package/work_package_custom_fields_spec.rb b/spec/models/work_package/work_package_custom_fields_spec.rb index 83be8c80c2a4..18a296a9d08f 100644 --- a/spec/models/work_package/work_package_custom_fields_spec.rb +++ b/spec/models/work_package/work_package_custom_fields_spec.rb @@ -457,5 +457,14 @@ def self.change_custom_field_value(work_package, value, save: true) it "offers a field the applied variant's form configuration shows" do expect(work_package.available_custom_fields).to include(field) end + + it "picks up a field the form configuration gained after an earlier lookup" do + later_field = create(:work_package_custom_field) + work_package.available_custom_fields.to_a + + type.default_variant.custom_field_ids |= [later_field.id] + + expect(described_class.find(work_package.id).available_custom_fields).to include(later_field) + end end end diff --git a/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb b/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb index 95849b754afc..1134731404e8 100644 --- a/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb +++ b/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb @@ -1049,6 +1049,44 @@ def jira_list_field(id:, name:, schema:, context_groups: nil) end end + describe "a field whose first value appears on a later issue of an already imported type" do + let!(:jira_field) do + create(:jira_field, jira_import:, + origin_id: "customfield_10275", + payload: { + "id" => "customfield_10275", + "name" => "CF Text", + "schema" => { + "type" => "string", + "custom" => "com.atlassian.jira.plugin.system.customfieldtypes:textarea", + "customId" => 10275 + } + }) + end + let!(:jira_issue_without_value) do + create(:jira_issue, jira_import:, + origin_id: "10199", + jira_project:, + payload: issue_payload.deep_dup.tap do |payload| + payload["key"] = "DYX-3" + payload["fields"]["summary"] = "Issue without the text value" + payload["fields"].delete("customfield_10275") + end) + end + let!(:jira_issue) do + create(:jira_issue, jira_import:, + origin_id: "10200", + jira_project:, + payload: issue_payload) + end + + before { import_project } + + it "sets the value the later issue is the first to carry" do + expect(cf_value("CF Text")).to include("**bold**") + end + end + describe "all custom field types in a single import run", with_ee: [:custom_field_hierarchies] do # Registers all field types at once and verifies the correct number of # OP custom fields are created: From 838b658c876405246a9836d75fe6a9e05bf0770a Mon Sep 17 00:00:00 2001 From: Andrej <77627197+as-op@users.noreply.github.com> Date: Mon, 26 Oct 2026 13:30:16 +0100 Subject: [PATCH 2/2] Update spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb Co-authored-by: Max Mulatz --- .../jira_create_project_work_packages_job_custom_fields_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb b/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb index 1134731404e8..a442e1f83cd4 100644 --- a/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb +++ b/spec/workers/import/jira_create_project_work_packages_job_custom_fields_spec.rb @@ -1082,7 +1082,7 @@ def jira_list_field(id:, name:, schema:, context_groups: nil) before { import_project } - it "sets the value the later issue is the first to carry" do + it "sets the field's value on the issue that introduced it" do expect(cf_value("CF Text")).to include("**bold**") end end