feat(machines) : ajoute le clonage par catégorie (structure seule)
Nouveau mode de clonage de machine via le paramètre `mode` de
POST /api/machines/{id}/clone :
- mode "full" (défaut) : comportement inchangé (clone complet)
- mode "structure" : ne recopie que les catégories des slots
(modelType), composant/pièce/produit concrets laissés vides
(slots à compléter), sans overrides ni custom field values
Front : sélecteur de mode dans la page de création de machine,
visible uniquement quand une machine source est choisie.
This commit is contained in:
@@ -308,4 +308,88 @@ class MachineContextCustomFieldTest extends AbstractApiTestCase
|
||||
$this->assertCount(1, $sourceLink['contextCustomFieldValues']);
|
||||
$this->assertSame('1500', $sourceLink['contextCustomFieldValues'][0]['value']);
|
||||
}
|
||||
|
||||
public function testCloneMachineStructureModeKeepsCategoriesWithoutConcreteEntities(): void
|
||||
{
|
||||
$client = $this->createGestionnaireClient();
|
||||
|
||||
$site = $this->createSite('Site Structure');
|
||||
$compType = $this->createModelType('Motor Struct', 'MOTST', ModelCategory::COMPONENT);
|
||||
$pieceType = $this->createModelType('Bearing Struct', 'BRGST', ModelCategory::PIECE);
|
||||
$contextField = $this->createCustomField(
|
||||
name: 'RPM Struct',
|
||||
type: 'number',
|
||||
typeComposant: $compType,
|
||||
machineContextOnly: true,
|
||||
);
|
||||
|
||||
$source = $this->createMachine('Source Struct Machine', $site);
|
||||
$composant = $this->createComposant('Motor ST', 'MOTST-001', $compType);
|
||||
$componentLink = $this->createMachineComponentLink($source, $composant);
|
||||
$piece = $this->createPiece('Bearing ST', 'BRGST-001', $pieceType);
|
||||
$this->createMachinePieceLink($source, $piece, $componentLink);
|
||||
|
||||
$this->createCustomFieldValue(
|
||||
customField: $contextField,
|
||||
value: '4200',
|
||||
composant: $composant,
|
||||
machineComponentLink: $componentLink,
|
||||
);
|
||||
|
||||
$response = $client->request('POST', '/api/machines/'.$source->getId().'/clone', [
|
||||
'json' => [
|
||||
'name' => 'Cloned Struct Machine',
|
||||
'siteId' => $site->getId(),
|
||||
'mode' => 'structure',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(201);
|
||||
$data = $response->toArray();
|
||||
|
||||
// Component slot: category preserved, concrete component dropped, no context values.
|
||||
$clonedComponent = $data['componentLinks'][0] ?? null;
|
||||
$this->assertNotNull($clonedComponent, 'Structure clone should expose the component slot');
|
||||
$this->assertTrue($clonedComponent['pendingEntity']);
|
||||
$this->assertNull($clonedComponent['composantId']);
|
||||
$this->assertSame($compType->getId(), $clonedComponent['modelTypeId']);
|
||||
$this->assertCount(0, $clonedComponent['contextCustomFieldValues']);
|
||||
|
||||
// Piece slot: category preserved, concrete piece dropped.
|
||||
$clonedPiece = $data['pieceLinks'][0] ?? null;
|
||||
$this->assertNotNull($clonedPiece, 'Structure clone should expose the piece slot');
|
||||
$this->assertTrue($clonedPiece['pendingEntity']);
|
||||
$this->assertNull($clonedPiece['pieceId']);
|
||||
$this->assertSame($pieceType->getId(), $clonedPiece['modelTypeId']);
|
||||
|
||||
// Source machine stays intact (still has its concrete component).
|
||||
$sourceData = $client->request('GET', '/api/machines/'.$source->getId().'/structure')->toArray();
|
||||
$this->assertFalse($sourceData['componentLinks'][0]['pendingEntity']);
|
||||
$this->assertSame($composant->getId(), $sourceData['componentLinks'][0]['composantId']);
|
||||
}
|
||||
|
||||
public function testCloneMachineFullModeStillCopiesConcreteEntities(): void
|
||||
{
|
||||
$client = $this->createGestionnaireClient();
|
||||
|
||||
$site = $this->createSite('Site Full');
|
||||
$compType = $this->createModelType('Motor Full', 'MOTFL', ModelCategory::COMPONENT);
|
||||
$source = $this->createMachine('Source Full Machine', $site);
|
||||
$composant = $this->createComposant('Motor FL', 'MOTFL-001', $compType);
|
||||
$this->createMachineComponentLink($source, $composant);
|
||||
|
||||
$response = $client->request('POST', '/api/machines/'.$source->getId().'/clone', [
|
||||
'json' => [
|
||||
'name' => 'Cloned Full Machine',
|
||||
'siteId' => $site->getId(),
|
||||
'mode' => 'full',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(201);
|
||||
$clonedComponent = $response->toArray()['componentLinks'][0] ?? null;
|
||||
$this->assertNotNull($clonedComponent);
|
||||
$this->assertFalse($clonedComponent['pendingEntity']);
|
||||
$this->assertSame($composant->getId(), $clonedComponent['composantId']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user