fix(custom-fields) : match by orderIndex to prevent value loss on rename

When a ModelType's custom field was renamed without sending the field ID,
the service would create a new CustomField instead of reusing the existing
one, orphaning all CustomFieldValues. Now matches by orderIndex as fallback
before name, preserving the link to existing values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-24 08:36:59 +01:00
parent 509c4d2247
commit 4468fd7cdf
3 changed files with 63 additions and 5 deletions

View File

@@ -192,12 +192,14 @@ class SkeletonStructureService
['orderIndex' => 'ASC']
);
// Index existing by ID and by name for matching
$existingById = [];
$existingByName = [];
// Index existing by ID, name and orderIndex for matching
$existingById = [];
$existingByName = [];
$existingByOrderIndex = [];
foreach ($existingFields as $cf) {
$existingById[$cf->getId()] = $cf;
$existingByName[$cf->getName()] = $cf;
$existingById[$cf->getId()] = $cf;
$existingByName[$cf->getName()] = $cf;
$existingByOrderIndex[$cf->getOrderIndex()][] = $cf;
}
$processedIds = [];
@@ -211,6 +213,14 @@ class SkeletonStructureService
$fieldId = $fieldData['customFieldId'] ?? $fieldData['id'] ?? null;
if ($fieldId && isset($existingById[$fieldId])) {
$existingField = $existingById[$fieldId];
} elseif (!empty($existingByOrderIndex[$normalized['orderIndex']])) {
foreach ($existingByOrderIndex[$normalized['orderIndex']] as $candidate) {
if (!isset($processedIds[$candidate->getId()])) {
$existingField = $candidate;
break;
}
}
} elseif (isset($existingByName[$normalized['name']]) && !isset($processedIds[$existingByName[$normalized['name']]->getId()])) {
$existingField = $existingByName[$normalized['name']];
}