fix(structure) : stabilize piece/component/product ordering in machines

All findBy(['machine' => ...]) queries now sort by createdAt ASC.
Without explicit ORDER BY, PostgreSQL returned rows in heap order which
changed on every INSERT, causing the displayed order to shuffle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-24 09:02:36 +01:00
parent 06ce9fb1f2
commit 3b35598b07
3 changed files with 18 additions and 18 deletions

View File

@@ -53,9 +53,9 @@ class MachineStructureController extends AbstractController
return $this->json(['success' => false, 'error' => 'Machine not found.'], 404);
}
$componentLinks = $this->machineComponentLinkRepository->findBy(['machine' => $machine]);
$pieceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $machine]);
$productLinks = $this->machineProductLinkRepository->findBy(['machine' => $machine]);
$componentLinks = $this->machineComponentLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']);
$pieceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']);
$productLinks = $this->machineProductLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']);
return $this->json($this->normalizeStructureResponse(
$machine,
@@ -159,9 +159,9 @@ class MachineStructureController extends AbstractController
$this->entityManager->flush();
$componentLinks = $this->machineComponentLinkRepository->findBy(['machine' => $newMachine]);
$pieceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $newMachine]);
$productLinks = $this->machineProductLinkRepository->findBy(['machine' => $newMachine]);
$componentLinks = $this->machineComponentLinkRepository->findBy(['machine' => $newMachine], ['createdAt' => 'ASC']);
$pieceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $newMachine], ['createdAt' => 'ASC']);
$productLinks = $this->machineProductLinkRepository->findBy(['machine' => $newMachine], ['createdAt' => 'ASC']);
return $this->json($this->normalizeStructureResponse(
$newMachine,
@@ -209,7 +209,7 @@ class MachineStructureController extends AbstractController
*/
private function cloneComponentLinks(Machine $source, Machine $target): array
{
$sourceLinks = $this->machineComponentLinkRepository->findBy(['machine' => $source]);
$sourceLinks = $this->machineComponentLinkRepository->findBy(['machine' => $source], ['createdAt' => 'ASC']);
$linkMap = [];
// First pass: create all links without parent relationships
@@ -242,7 +242,7 @@ class MachineStructureController extends AbstractController
*/
private function clonePieceLinks(Machine $source, Machine $target, array $componentLinkMap): array
{
$sourceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $source]);
$sourceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $source], ['createdAt' => 'ASC']);
$linkMap = [];
foreach ($sourceLinks as $link) {
@@ -276,7 +276,7 @@ class MachineStructureController extends AbstractController
array $componentLinkMap,
array $pieceLinkMap,
): void {
$sourceLinks = $this->machineProductLinkRepository->findBy(['machine' => $source]);
$sourceLinks = $this->machineProductLinkRepository->findBy(['machine' => $source], ['createdAt' => 'ASC']);
$linkMap = [];
// First pass: create all links
@@ -319,7 +319,7 @@ class MachineStructureController extends AbstractController
private function applyComponentLinks(Machine $machine, array $payload): array|JsonResponse
{
$existing = $this->indexLinksById($this->machineComponentLinkRepository->findBy(['machine' => $machine]));
$existing = $this->indexLinksById($this->machineComponentLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']));
$keepIds = [];
$pendingParents = [];
$links = [];
@@ -376,7 +376,7 @@ class MachineStructureController extends AbstractController
private function applyPieceLinks(Machine $machine, array $payload, array $componentLinks): array|JsonResponse
{
$existing = $this->indexLinksById($this->machinePieceLinkRepository->findBy(['machine' => $machine]));
$existing = $this->indexLinksById($this->machinePieceLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']));
$componentIndex = $this->indexLinksById($componentLinks);
$keepIds = [];
$pendingParents = [];
@@ -443,7 +443,7 @@ class MachineStructureController extends AbstractController
array $componentLinks,
array $pieceLinks,
): array|JsonResponse {
$existing = $this->indexLinksById($this->machineProductLinkRepository->findBy(['machine' => $machine]));
$existing = $this->indexLinksById($this->machineProductLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']));
$componentIndex = $this->indexLinksById($componentLinks);
$pieceIndex = $this->indexLinksById($pieceLinks);
$keepIds = [];

View File

@@ -123,7 +123,7 @@ class CloneMachineTool
*/
private function cloneComponentLinks(Machine $source, Machine $target): array
{
$sourceLinks = $this->machineComponentLinkRepository->findBy(['machine' => $source]);
$sourceLinks = $this->machineComponentLinkRepository->findBy(['machine' => $source], ['createdAt' => 'ASC']);
$linkMap = [];
// First pass: create all links without parent relationships
@@ -156,7 +156,7 @@ class CloneMachineTool
*/
private function clonePieceLinks(Machine $source, Machine $target, array $componentLinkMap): array
{
$sourceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $source]);
$sourceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $source], ['createdAt' => 'ASC']);
$linkMap = [];
foreach ($sourceLinks as $link) {
@@ -190,7 +190,7 @@ class CloneMachineTool
array $componentLinkMap,
array $pieceLinkMap,
): void {
$sourceLinks = $this->machineProductLinkRepository->findBy(['machine' => $source]);
$sourceLinks = $this->machineProductLinkRepository->findBy(['machine' => $source], ['createdAt' => 'ASC']);
$linkMap = [];
// First pass: create all links

View File

@@ -46,9 +46,9 @@ class MachineStructureTool
$this->mcpError('not_found', "Machine not found: {$machineId}");
}
$componentLinks = $this->machineComponentLinkRepository->findBy(['machine' => $machine]);
$pieceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $machine]);
$productLinks = $this->machineProductLinkRepository->findBy(['machine' => $machine]);
$componentLinks = $this->machineComponentLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']);
$pieceLinks = $this->machinePieceLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']);
$productLinks = $this->machineProductLinkRepository->findBy(['machine' => $machine], ['createdAt' => 'ASC']);
return $this->jsonResponse($this->normalizeStructureResponse(
$machine,