createModelType('Roulement', 'ROUL-010', ModelCategory::PIECE); $mt->setReferenceFormula('{serie}{diametre}{type}'); $mt->setRequiredFieldsForReference(['serie', 'diametre', 'type']); $em = $this->getEntityManager(); $em->flush(); $cfSerie = $this->createCustomField('serie', 'text', typePiece: $mt); $cfDiametre = $this->createCustomField('diametre', 'text', typePiece: $mt); $cfType = $this->createCustomField('type', 'text', typePiece: $mt); $piece = $this->createPiece('Roulement Auto', null, $mt); $this->createCustomFieldValue($cfSerie, '22', piece: $piece); $this->createCustomFieldValue($cfDiametre, '07', piece: $piece); $this->createCustomFieldValue($cfType, 'K', piece: $piece); $client = $this->createViewerClient(); $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['referenceAuto' => '2207K']); } public function testReferenceAutoNullWhenNoFormula(): void { $mt = $this->createModelType('Galet', 'GAL-010', ModelCategory::PIECE); $piece = $this->createPiece('Galet Auto', null, $mt); $client = $this->createViewerClient(); $response = $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertResponseIsSuccessful(); $data = $response->toArray(); self::assertArrayNotHasKey('referenceAuto', $data, 'referenceAuto should not be serialized when null'); } public function testReferenceAutoNullWhenRequiredFieldsMissing(): void { $mt = $this->createModelType('Palier', 'PAL-010', ModelCategory::PIECE); $mt->setReferenceFormula('SNU {taille}'); $mt->setRequiredFieldsForReference(['taille']); $em = $this->getEntityManager(); $em->flush(); $piece = $this->createPiece('Palier Sans Champ', null, $mt); $client = $this->createViewerClient(); $response = $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertResponseIsSuccessful(); $data = $response->toArray(); self::assertArrayNotHasKey('referenceAuto', $data, 'referenceAuto should not be serialized when required fields missing'); } public function testReferenceAutoUpdatedWhenCustomFieldValueChanges(): void { $mt = $this->createModelType('Joint', 'JOINT-010', ModelCategory::PIECE); $mt->setReferenceFormula('U{taille}'); $em = $this->getEntityManager(); $em->flush(); $cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt); $piece = $this->createPiece('Joint Upd', null, $mt); $cfv = $this->createCustomFieldValue($cfTaille, '507', piece: $piece); $client = $this->createViewerClient(); $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['referenceAuto' => 'U507']); // Update CFV value via API $gClient = $this->createGestionnaireClient(); $gClient->request('PATCH', self::iri('custom_field_values', $cfv->getId()), [ 'headers' => ['Content-Type' => 'application/merge-patch+json'], 'json' => ['value' => '608'], ]); $this->assertResponseIsSuccessful(); // Re-read the Piece to check updated referenceAuto $viewer = $this->createViewerClient(); $viewer->request('GET', self::iri('pieces', $piece->getId())); $this->assertJsonContains(['referenceAuto' => 'U608']); } public function testReferenceAutoNullAfterRequiredCfvDeleted(): void { $mt = $this->createModelType('Joint Del', 'JOINT-011', ModelCategory::PIECE); $mt->setReferenceFormula('U{taille}'); $mt->setRequiredFieldsForReference(['taille']); $em = $this->getEntityManager(); $em->flush(); $cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt); $piece = $this->createPiece('Joint Del', null, $mt); $cfv = $this->createCustomFieldValue($cfTaille, '507', piece: $piece); $client = $this->createViewerClient(); $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertJsonContains(['referenceAuto' => 'U507']); // Delete the CFV $gClient = $this->createGestionnaireClient(); $gClient->request('DELETE', self::iri('custom_field_values', $cfv->getId())); $this->assertResponseStatusCodeSame(204); // Re-read piece — referenceAuto should now be absent (null = not serialized) $viewer = $this->createViewerClient(); $response = $viewer->request('GET', self::iri('pieces', $piece->getId())); $data = $response->toArray(); self::assertArrayNotHasKey('referenceAuto', $data, 'referenceAuto should be null after required CFV deleted'); } public function testReferenceAutoIsReadOnlyViaApi(): void { $piece = $this->createPiece('ReadOnly Test'); $client = $this->createGestionnaireClient(); $client->request('PATCH', self::iri('pieces', $piece->getId()), [ 'headers' => ['Content-Type' => 'application/merge-patch+json'], 'json' => ['referenceAuto' => 'HACKED'], ]); $this->assertResponseIsSuccessful(); // referenceAuto should still be null (no formula) — subscriber overwrites $viewer = $this->createViewerClient(); $response = $viewer->request('GET', self::iri('pieces', $piece->getId())); $data = $response->toArray(); self::assertArrayNotHasKey('referenceAuto', $data, 'referenceAuto should not be settable via API'); } public function testReferenceAutoNormalizesLowercaseValues(): void { $mt = $this->createModelType('Roulement Norm', 'ROUL-011', ModelCategory::PIECE); $mt->setReferenceFormula('{serie}{diametre}{type}'); $em = $this->getEntityManager(); $em->flush(); $cfSerie = $this->createCustomField('serie', 'text', typePiece: $mt); $cfDiametre = $this->createCustomField('diametre', 'text', typePiece: $mt); $cfType = $this->createCustomField('type', 'text', typePiece: $mt); $piece = $this->createPiece('Roulement Norm', null, $mt); $this->createCustomFieldValue($cfSerie, '22', piece: $piece); $this->createCustomFieldValue($cfDiametre, '07', piece: $piece); $this->createCustomFieldValue($cfType, 'k', piece: $piece); $client = $this->createViewerClient(); $client->request('GET', self::iri('pieces', $piece->getId())); $this->assertResponseIsSuccessful(); $this->assertJsonContains(['referenceAuto' => '2207K']); } }