feat(api) : add machine count to category related items endpoint
This commit is contained in:
@@ -48,6 +48,39 @@
|
||||
<span class="whitespace-nowrap">{{ formatDate(row.createdAt) }}</span>
|
||||
</template>
|
||||
|
||||
<template #cell-composantCount="{ row }">
|
||||
<NuxtLink
|
||||
v-if="stats[row.id]?.composantCount"
|
||||
:to="`/catalogues/composants?constructeur=${row.id}`"
|
||||
class="badge badge-ghost badge-sm hover:badge-primary transition-colors"
|
||||
>
|
||||
{{ stats[row.id].composantCount }}
|
||||
</NuxtLink>
|
||||
<span v-else class="text-base-content/30">—</span>
|
||||
</template>
|
||||
|
||||
<template #cell-pieceCount="{ row }">
|
||||
<NuxtLink
|
||||
v-if="stats[row.id]?.pieceCount"
|
||||
:to="`/catalogues/pieces?constructeur=${row.id}`"
|
||||
class="badge badge-ghost badge-sm hover:badge-primary transition-colors"
|
||||
>
|
||||
{{ stats[row.id].pieceCount }}
|
||||
</NuxtLink>
|
||||
<span v-else class="text-base-content/30">—</span>
|
||||
</template>
|
||||
|
||||
<template #cell-machineCount="{ row }">
|
||||
<NuxtLink
|
||||
v-if="stats[row.id]?.machineCount"
|
||||
:to="`/machines?constructeur=${row.id}`"
|
||||
class="badge badge-ghost badge-sm hover:badge-primary transition-colors"
|
||||
>
|
||||
{{ stats[row.id].machineCount }}
|
||||
</NuxtLink>
|
||||
<span v-else class="text-base-content/30">—</span>
|
||||
</template>
|
||||
|
||||
<template #cell-actions="{ row }">
|
||||
<div class="flex items-center justify-end gap-2">
|
||||
<button class="btn btn-ghost btn-xs" @click="openEditModal(row)">
|
||||
@@ -103,6 +136,7 @@ import { formatPhone } from '~/utils/formatters/phone'
|
||||
import { formatFrenchDate } from '~/utils/date'
|
||||
import IconLucidePlus from '~icons/lucide/plus'
|
||||
|
||||
const api = useApi()
|
||||
const { canEdit } = usePermissions()
|
||||
const { constructeurs, loading, searchConstructeurs, createConstructeur, updateConstructeur, deleteConstructeur, loadConstructeurs } = useConstructeurs()
|
||||
const { showError } = useToast()
|
||||
@@ -112,12 +146,16 @@ const columns = [
|
||||
{ key: 'email', label: 'Email', sortable: true },
|
||||
{ key: 'phone', label: 'Téléphone', sortable: true },
|
||||
{ key: 'createdAt', label: 'Date de création', sortable: true },
|
||||
{ key: 'composantCount', label: 'Composants', align: 'center' },
|
||||
{ key: 'pieceCount', label: 'Pièces', align: 'center' },
|
||||
{ key: 'machineCount', label: 'Machines', align: 'center' },
|
||||
{ key: 'actions', label: 'Actions', align: 'right' },
|
||||
]
|
||||
|
||||
const searchTerm = ref('')
|
||||
const sortKey = usePersistedValue('constructeurs-sort', 'name')
|
||||
const sortDir = ref('asc')
|
||||
const stats = ref({})
|
||||
|
||||
const currentSort = computed(() => ({
|
||||
field: sortKey.value,
|
||||
@@ -236,5 +274,15 @@ const confirmDelete = async (constructeur) => {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => loadConstructeurs())
|
||||
const loadStats = async () => {
|
||||
const result = await api.get('/constructeurs/stats')
|
||||
if (result.success && result.data) {
|
||||
stats.value = result.data
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadConstructeurs()
|
||||
loadStats()
|
||||
})
|
||||
</script>
|
||||
|
||||
142
src/Controller/ModelTypeRelatedItemsController.php
Normal file
142
src/Controller/ModelTypeRelatedItemsController.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Composant;
|
||||
use App\Entity\MachineComponentLink;
|
||||
use App\Entity\MachinePieceLink;
|
||||
use App\Entity\MachineProductLink;
|
||||
use App\Entity\Piece;
|
||||
use App\Entity\Product;
|
||||
use App\Enum\ModelCategory;
|
||||
use App\Repository\ModelTypeRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route('/api/model_types/{id}')]
|
||||
final class ModelTypeRelatedItemsController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ModelTypeRepository $modelTypes,
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
#[Route('/related-items', name: 'api_model_type_related_items', methods: ['GET'])]
|
||||
public function relatedItems(string $id): JsonResponse
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_VIEWER');
|
||||
|
||||
$modelType = $this->modelTypes->find($id);
|
||||
|
||||
if (!$modelType) {
|
||||
return new JsonResponse(
|
||||
['message' => 'Catégorie introuvable.'],
|
||||
Response::HTTP_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
$items = match ($modelType->getCategory()) {
|
||||
ModelCategory::COMPONENT => $this->fetchComposantsWithMachineCount($id),
|
||||
ModelCategory::PIECE => $this->fetchPiecesWithMachineCount($id),
|
||||
ModelCategory::PRODUCT => $this->fetchProductsWithMachineCount($id),
|
||||
};
|
||||
|
||||
return new JsonResponse($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{id: string, name: string, reference: null|string, machineCount: int}>
|
||||
*/
|
||||
private function fetchComposantsWithMachineCount(string $modelTypeId): array
|
||||
{
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
$qb->select(
|
||||
'c.id',
|
||||
'c.name',
|
||||
'c.reference',
|
||||
'COALESCE(c.referenceAuto, c.reference) as displayReference',
|
||||
'COUNT(DISTINCT mcl.id) as machineCount',
|
||||
)
|
||||
->from(Composant::class, 'c')
|
||||
->leftJoin(MachineComponentLink::class, 'mcl', 'WITH', 'mcl.composant = c')
|
||||
->where('c.typeComposant = :modelTypeId')
|
||||
->setParameter('modelTypeId', $modelTypeId)
|
||||
->groupBy('c.id', 'c.name', 'c.reference', 'c.referenceAuto')
|
||||
->orderBy('c.name', 'ASC')
|
||||
;
|
||||
|
||||
return $this->formatResults($qb->getQuery()->getArrayResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{id: string, name: string, reference: null|string, machineCount: int}>
|
||||
*/
|
||||
private function fetchPiecesWithMachineCount(string $modelTypeId): array
|
||||
{
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
$qb->select(
|
||||
'p.id',
|
||||
'p.name',
|
||||
'p.reference',
|
||||
'COALESCE(p.referenceAuto, p.reference) as displayReference',
|
||||
'COUNT(DISTINCT mpl.id) as machineCount',
|
||||
)
|
||||
->from(Piece::class, 'p')
|
||||
->leftJoin(MachinePieceLink::class, 'mpl', 'WITH', 'mpl.piece = p')
|
||||
->where('p.typePiece = :modelTypeId')
|
||||
->setParameter('modelTypeId', $modelTypeId)
|
||||
->groupBy('p.id', 'p.name', 'p.reference', 'p.referenceAuto')
|
||||
->orderBy('p.name', 'ASC')
|
||||
;
|
||||
|
||||
return $this->formatResults($qb->getQuery()->getArrayResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array{id: string, name: string, reference: null|string, machineCount: int}>
|
||||
*/
|
||||
private function fetchProductsWithMachineCount(string $modelTypeId): array
|
||||
{
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
$qb->select(
|
||||
'pr.id',
|
||||
'pr.name',
|
||||
'pr.reference',
|
||||
'COUNT(DISTINCT mpl.id) as machineCount',
|
||||
)
|
||||
->from(Product::class, 'pr')
|
||||
->leftJoin(MachineProductLink::class, 'mpl', 'WITH', 'mpl.product = pr')
|
||||
->where('pr.typeProduct = :modelTypeId')
|
||||
->setParameter('modelTypeId', $modelTypeId)
|
||||
->groupBy('pr.id', 'pr.name', 'pr.reference')
|
||||
->orderBy('pr.name', 'ASC')
|
||||
;
|
||||
|
||||
return $this->formatResults($qb->getQuery()->getArrayResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $rows
|
||||
*
|
||||
* @return list<array{id: string, name: string, reference: null|string, machineCount: int}>
|
||||
*/
|
||||
private function formatResults(array $rows): array
|
||||
{
|
||||
return array_values(array_map(
|
||||
static fn (array $row): array => [
|
||||
'id' => (string) $row['id'],
|
||||
'name' => (string) ($row['name'] ?? ''),
|
||||
'reference' => isset($row['displayReference']) && '' !== $row['displayReference']
|
||||
? (string) $row['displayReference']
|
||||
: (isset($row['reference']) && '' !== $row['reference'] ? (string) $row['reference'] : null),
|
||||
'machineCount' => (int) $row['machineCount'],
|
||||
],
|
||||
$rows,
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user