feat(reference-auto) : add automatic reference generation for pieces
ModelType defines a formula with placeholders ({serie}{diametre}{type}).
ReferenceAutoGenerator resolves it from CustomFieldValues with trim+uppercase normalisation.
ReferenceAutoSubscriber (onFlush) recalculates on Piece/CFV insert/update/delete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,3 +64,8 @@ when@test:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
public: true
|
||||
|
||||
App\Service\ReferenceAutoGenerator:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
public: true
|
||||
|
||||
@@ -73,6 +73,14 @@ class ModelType
|
||||
#[Groups(['type_machine:read', 'model_type:read', 'model_type:write'])]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
#[Groups(['model_type:read', 'model_type:write'])]
|
||||
private ?string $referenceFormula = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||
#[Groups(['model_type:read', 'model_type:write'])]
|
||||
private ?array $requiredFieldsForReference = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, name: 'createdAt')]
|
||||
#[Groups(['model_type:read'])]
|
||||
private DateTimeImmutable $createdAt;
|
||||
@@ -215,6 +223,30 @@ class ModelType
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReferenceFormula(): ?string
|
||||
{
|
||||
return $this->referenceFormula;
|
||||
}
|
||||
|
||||
public function setReferenceFormula(?string $referenceFormula): static
|
||||
{
|
||||
$this->referenceFormula = $referenceFormula;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRequiredFieldsForReference(): ?array
|
||||
{
|
||||
return $this->requiredFieldsForReference;
|
||||
}
|
||||
|
||||
public function setRequiredFieldsForReference(?array $requiredFieldsForReference): static
|
||||
{
|
||||
$this->requiredFieldsForReference = $requiredFieldsForReference;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
#[Groups(['model_type:read', 'product:read', 'composant:read', 'piece:read'])]
|
||||
public function getStructure(): ?array
|
||||
{
|
||||
|
||||
@@ -63,6 +63,10 @@ class Piece
|
||||
#[Groups(['piece:read'])]
|
||||
private ?string $reference = null;
|
||||
|
||||
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
|
||||
#[Groups(['piece:read'])]
|
||||
private ?string $referenceAuto = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
#[Groups(['piece:read'])]
|
||||
private ?string $description = null;
|
||||
@@ -179,6 +183,21 @@ class Piece
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReferenceAuto(): ?string
|
||||
{
|
||||
return $this->referenceAuto;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal used by ReferenceAutoSubscriber only — not part of the public API
|
||||
*/
|
||||
public function setReferenceAuto(?string $referenceAuto): static
|
||||
{
|
||||
$this->referenceAuto = $referenceAuto;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
|
||||
77
src/EventSubscriber/ReferenceAutoSubscriber.php
Normal file
77
src/EventSubscriber/ReferenceAutoSubscriber.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
|
||||
use App\Entity\CustomFieldValue;
|
||||
use App\Entity\Piece;
|
||||
use App\Service\ReferenceAutoGenerator;
|
||||
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
|
||||
use Doctrine\ORM\Event\OnFlushEventArgs;
|
||||
use Doctrine\ORM\Events;
|
||||
|
||||
#[AsDoctrineListener(event: Events::onFlush)]
|
||||
final class ReferenceAutoSubscriber
|
||||
{
|
||||
public function __construct(private readonly ReferenceAutoGenerator $generator) {}
|
||||
|
||||
public function onFlush(OnFlushEventArgs $args): void
|
||||
{
|
||||
$em = $args->getObjectManager();
|
||||
$uow = $em->getUnitOfWork();
|
||||
|
||||
$piecesToRecalculate = [];
|
||||
|
||||
foreach ($uow->getScheduledEntityInsertions() as $entity) {
|
||||
if ($entity instanceof Piece) {
|
||||
$piecesToRecalculate[$entity->getId()] = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($uow->getScheduledEntityUpdates() as $entity) {
|
||||
if ($entity instanceof Piece) {
|
||||
$piecesToRecalculate[$entity->getId()] = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
// For CFV insertions: the new CFV is not yet in the DB, so Piece's lazy-loaded
|
||||
// collection won't contain it. We must add it manually so the generator sees it.
|
||||
foreach ($uow->getScheduledEntityInsertions() as $entity) {
|
||||
if ($entity instanceof CustomFieldValue && $entity->getPiece()) {
|
||||
$piece = $entity->getPiece();
|
||||
if (!$piece->getCustomFieldValues()->contains($entity)) {
|
||||
$piece->getCustomFieldValues()->add($entity);
|
||||
}
|
||||
$piecesToRecalculate[$piece->getId()] = $piece;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($uow->getScheduledEntityUpdates() as $entity) {
|
||||
if ($entity instanceof CustomFieldValue && $entity->getPiece()) {
|
||||
$piece = $entity->getPiece();
|
||||
$piecesToRecalculate[$piece->getId()] = $piece;
|
||||
}
|
||||
}
|
||||
|
||||
// For CFV deletions: remove from collection so the generator doesn't see stale values.
|
||||
foreach ($uow->getScheduledEntityDeletions() as $entity) {
|
||||
if ($entity instanceof CustomFieldValue && $entity->getPiece()) {
|
||||
$piece = $entity->getPiece();
|
||||
$piece->getCustomFieldValues()->removeElement($entity);
|
||||
$piecesToRecalculate[$piece->getId()] = $piece;
|
||||
}
|
||||
}
|
||||
|
||||
$meta = $em->getClassMetadata(Piece::class);
|
||||
|
||||
foreach ($piecesToRecalculate as $piece) {
|
||||
$newRef = $this->generator->generate($piece);
|
||||
|
||||
if ($piece->getReferenceAuto() !== $newRef) {
|
||||
$piece->setReferenceAuto($newRef);
|
||||
$uow->recomputeSingleEntityChangeSet($meta, $piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/Service/ReferenceAutoGenerator.php
Normal file
54
src/Service/ReferenceAutoGenerator.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\CustomFieldValue;
|
||||
use App\Entity\Piece;
|
||||
|
||||
class ReferenceAutoGenerator
|
||||
{
|
||||
public function generate(Piece $piece): ?string
|
||||
{
|
||||
$modelType = $piece->getTypePiece();
|
||||
|
||||
if (!$modelType || !$modelType->getReferenceFormula()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$valueMap = $this->buildValueMap($piece);
|
||||
|
||||
$requiredFields = $modelType->getRequiredFieldsForReference();
|
||||
|
||||
if ($requiredFields) {
|
||||
foreach ($requiredFields as $fieldName) {
|
||||
if (!isset($valueMap[$fieldName]) || '' === $valueMap[$fieldName]) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return preg_replace_callback('/\{(\w+)\}/', static function (array $matches) use ($valueMap): string {
|
||||
return $valueMap[$matches[1]] ?? '';
|
||||
}, $modelType->getReferenceFormula());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a map of fieldName → normalized value from the Piece's CustomFieldValues.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function buildValueMap(Piece $piece): array
|
||||
{
|
||||
$map = [];
|
||||
|
||||
/** @var CustomFieldValue $cfv */
|
||||
foreach ($piece->getCustomFieldValues() as $cfv) {
|
||||
$normalized = mb_strtoupper(trim($cfv->getValue()));
|
||||
$map[$cfv->getCustomField()->getName()] = $normalized;
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
}
|
||||
178
tests/Api/Entity/PieceReferenceAutoTest.php
Normal file
178
tests/Api/Entity/PieceReferenceAutoTest.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Api\Entity;
|
||||
|
||||
use App\Enum\ModelCategory;
|
||||
use App\Tests\AbstractApiTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class PieceReferenceAutoTest extends AbstractApiTestCase
|
||||
{
|
||||
public function testReferenceAutoGeneratedAfterAllCfvCreated(): void
|
||||
{
|
||||
$mt = $this->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']);
|
||||
}
|
||||
}
|
||||
167
tests/Service/ReferenceAutoGeneratorTest.php
Normal file
167
tests/Service/ReferenceAutoGeneratorTest.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Service;
|
||||
|
||||
use App\Enum\ModelCategory;
|
||||
use App\Tests\AbstractApiTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ReferenceAutoGeneratorTest extends AbstractApiTestCase
|
||||
{
|
||||
public function testGenerateWithFormula(): void
|
||||
{
|
||||
$mt = $this->createModelType('Roulement', 'ROUL-001', 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 Test', null, $mt);
|
||||
|
||||
$this->createCustomFieldValue($cfSerie, '22', piece: $piece);
|
||||
$this->createCustomFieldValue($cfDiametre, '07', piece: $piece);
|
||||
$this->createCustomFieldValue($cfType, 'K', piece: $piece);
|
||||
|
||||
$em->refresh($piece);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertSame('2207K', $result);
|
||||
}
|
||||
|
||||
public function testGenerateNormalizesValues(): void
|
||||
{
|
||||
$mt = $this->createModelType('Roulement Norm', 'ROUL-002', 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 Norm', null, $mt);
|
||||
|
||||
$this->createCustomFieldValue($cfSerie, ' 22 ', piece: $piece);
|
||||
$this->createCustomFieldValue($cfDiametre, '07', piece: $piece);
|
||||
$this->createCustomFieldValue($cfType, 'k', piece: $piece);
|
||||
|
||||
$em->refresh($piece);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertSame('2207K', $result);
|
||||
}
|
||||
|
||||
public function testGenerateReturnsNullWithoutFormula(): void
|
||||
{
|
||||
$mt = $this->createModelType('Galet', 'GAL-001', ModelCategory::PIECE);
|
||||
$piece = $this->createPiece('Galet Test', null, $mt);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertNull($result);
|
||||
}
|
||||
|
||||
public function testGenerateReturnsNullWhenNoModelType(): void
|
||||
{
|
||||
$piece = $this->createPiece('Orphan Piece');
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertNull($result);
|
||||
}
|
||||
|
||||
public function testGenerateReturnsNullWhenRequiredFieldsMissing(): void
|
||||
{
|
||||
$mt = $this->createModelType('Palier', 'PAL-001', ModelCategory::PIECE);
|
||||
$mt->setReferenceFormula('SNU {taille}');
|
||||
$mt->setRequiredFieldsForReference(['taille']);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$em->flush();
|
||||
|
||||
$piece = $this->createPiece('Palier Test', null, $mt);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertNull($result);
|
||||
}
|
||||
|
||||
public function testGenerateReturnsNullWhenRequiredFieldEmpty(): void
|
||||
{
|
||||
$mt = $this->createModelType('Palier Vide', 'PAL-003', ModelCategory::PIECE);
|
||||
$mt->setReferenceFormula('SNU {taille}');
|
||||
$mt->setRequiredFieldsForReference(['taille']);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$em->flush();
|
||||
|
||||
$cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt);
|
||||
$piece = $this->createPiece('Palier Vide', null, $mt);
|
||||
$this->createCustomFieldValue($cfTaille, ' ', piece: $piece);
|
||||
|
||||
$em->refresh($piece);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertNull($result);
|
||||
}
|
||||
|
||||
public function testGenerateWithStaticTextInFormula(): void
|
||||
{
|
||||
$mt = $this->createModelType('Joint', 'JOINT-001', ModelCategory::PIECE);
|
||||
$mt->setReferenceFormula('U{taille}');
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$em->flush();
|
||||
|
||||
$cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt);
|
||||
$piece = $this->createPiece('Joint Test', null, $mt);
|
||||
$this->createCustomFieldValue($cfTaille, '507', piece: $piece);
|
||||
|
||||
$em->refresh($piece);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertSame('U507', $result);
|
||||
}
|
||||
|
||||
public function testGenerateWithSpaceInFormula(): void
|
||||
{
|
||||
$mt = $this->createModelType('Palier2', 'PAL-002', ModelCategory::PIECE);
|
||||
$mt->setReferenceFormula('SNU {taille}');
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$em->flush();
|
||||
|
||||
$cfTaille = $this->createCustomField('taille', 'text', typePiece: $mt);
|
||||
$piece = $this->createPiece('Palier Test 2', null, $mt);
|
||||
$this->createCustomFieldValue($cfTaille, '507', piece: $piece);
|
||||
|
||||
$em->refresh($piece);
|
||||
|
||||
$generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator');
|
||||
$result = $generator->generate($piece);
|
||||
|
||||
self::assertSame('SNU 507', $result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user