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:
@@ -382,6 +382,8 @@ abstract class AbstractApiTestCase extends ApiTestCase
|
||||
string $value = 'test value',
|
||||
?Machine $machine = null,
|
||||
?Composant $composant = null,
|
||||
?Piece $piece = null,
|
||||
?Product $product = null,
|
||||
): CustomFieldValue {
|
||||
$cfv = new CustomFieldValue();
|
||||
$cfv->setValue($value);
|
||||
@@ -392,6 +394,12 @@ abstract class AbstractApiTestCase extends ApiTestCase
|
||||
if (null !== $composant) {
|
||||
$cfv->setComposant($composant);
|
||||
}
|
||||
if (null !== $piece) {
|
||||
$cfv->setPiece($piece);
|
||||
}
|
||||
if (null !== $product) {
|
||||
$cfv->setProduct($product);
|
||||
}
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$em->persist($cfv);
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Api\Entity;
|
||||
|
||||
use App\Entity\CustomField;
|
||||
use App\Entity\CustomFieldValue;
|
||||
use App\Enum\ModelCategory;
|
||||
use App\Tests\AbstractApiTestCase;
|
||||
|
||||
@@ -280,4 +282,42 @@ class ModelTypeTest extends AbstractApiTestCase
|
||||
$this->assertSame($productType->getId(), $data['structure']['products'][0]['typeProductId']);
|
||||
$this->assertSame('GR', $data['structure']['products'][0]['familyCode']);
|
||||
}
|
||||
|
||||
public function testPatchPieceStructureRenameKeepsCustomFieldValuesWhenIdIsMissing(): void
|
||||
{
|
||||
$type = $this->createModelType('Arbre', 'ARB-001', ModelCategory::PIECE);
|
||||
$piece = $this->createPiece('Arbre de test', 'ARB-TEST', $type);
|
||||
$field = $this->createCustomField('diamètre', 'text', typePiece: $type, orderIndex: 0);
|
||||
$this->createCustomFieldValue($field, '35 mm', piece: $piece);
|
||||
|
||||
$client = $this->createGestionnaireClient();
|
||||
$client->request('PATCH', self::iri('model_types', $type->getId()), [
|
||||
'headers' => ['Content-Type' => 'application/merge-patch+json'],
|
||||
'json' => [
|
||||
'structure' => [
|
||||
'customFields' => [[
|
||||
'name' => 'Diamètre',
|
||||
'type' => 'text',
|
||||
'required' => false,
|
||||
'orderIndex' => 0,
|
||||
]],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$em->clear();
|
||||
|
||||
$fields = $em->getRepository(CustomField::class)->findBy(['typePiece' => $type], ['orderIndex' => 'ASC']);
|
||||
$this->assertCount(1, $fields);
|
||||
$this->assertSame($field->getId(), $fields[0]->getId(), 'Renaming must reuse the existing CustomField');
|
||||
$this->assertSame('Diamètre', $fields[0]->getName());
|
||||
|
||||
$values = $em->getRepository(CustomFieldValue::class)->findBy(['piece' => $piece]);
|
||||
$this->assertCount(1, $values);
|
||||
$this->assertSame('35 mm', $values[0]->getValue(), 'Existing custom field value must be preserved');
|
||||
$this->assertSame($field->getId(), $values[0]->getCustomField()->getId());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user