diff --git a/src/Repository/ClientRepository.php b/src/Repository/ClientRepository.php index 4e96160..72f8b17 100644 --- a/src/Repository/ClientRepository.php +++ b/src/Repository/ClientRepository.php @@ -20,6 +20,7 @@ class ClientRepository extends AbstractRepository { $entityManager = $this->getEntityManager(); + // Obtener el path de la unidad organizativa raíz $query = $entityManager->createQuery( 'SELECT o.path FROM App\Entity\OrganizationalUnit o @@ -33,6 +34,7 @@ class ClientRepository extends AbstractRepository $path = $result['path'] . '/%'; + // Obtener las unidades organizativas descendientes $query = $entityManager->createQuery( 'SELECT o.id FROM App\Entity\OrganizationalUnit o @@ -43,15 +45,89 @@ class ClientRepository extends AbstractRepository $unitIds = array_column($query->getArrayResult(), 'id'); + // Construcción de la consulta con filtros dinámicos $qb = $entityManager->createQueryBuilder(); $qb->select('c') - ->from(Client::class, 'c') + ->from('App\Entity\Client', 'c') ->where('c.organizationalUnit IN (:unitIds)') ->setParameter('unitIds', $unitIds); + // Aplicar dinámicamente los filtros recibidos foreach ($filters as $key => $value) { if ($key === 'order' || $key === 'page' || $key === 'itemsPerPage' || $key === 'organizationalUnit.id') { - continue; + continue; // No son filtros de búsqueda + } + + if ($key === 'exists') { + foreach ($value as $field => $existsValue) { + if ($existsValue === 'true') { + $qb->andWhere("c.$field IS NOT NULL"); + } elseif ($existsValue === 'false') { + $qb->andWhere("c.$field IS NULL"); + } + } + } else { + // Si es un campo normal, añadirlo como filtro + $qb->andWhere("c.$key = :$key")->setParameter($key, $value); + } + } + + // Aplicar ordenación si existe + if (isset($filters['order']) && is_array($filters['order'])) { + foreach ($filters['order'] as $field => $direction) { + if (in_array(strtolower($direction), ['asc', 'desc'])) { + $qb->addOrderBy("c.$field", $direction); + } + } + } + + // Aplicar paginación + if (isset($filters['page']) && isset($filters['itemsPerPage'])) { + $page = max(1, (int) $filters['page']); + $itemsPerPage = max(1, (int) $filters['itemsPerPage']); + $qb->setFirstResult(($page - 1) * $itemsPerPage) + ->setMaxResults($itemsPerPage); + } + + return $qb->getQuery()->getResult(); + } + + public function countClientsByOrganizationalUnitAndDescendants(int $organizationalUnitId, array $filters = []): int + { + $entityManager = $this->getEntityManager(); + + // Obtener el path de la unidad organizativa raíz + $query = $entityManager->createQuery( + 'SELECT o.path FROM App\Entity\OrganizationalUnit o WHERE o.id = :id' + )->setParameter('id', $organizationalUnitId); + + $result = $query->getOneOrNullResult(); + if (!$result) { + return 0; + } + + $path = $result['path'] . '/%'; + + // Obtener las unidades organizativas descendientes + $query = $entityManager->createQuery( + 'SELECT o.id FROM App\Entity\OrganizationalUnit o WHERE o.id = :id OR o.path LIKE :path' + ) + ->setParameter('id', $organizationalUnitId) + ->setParameter('path', $path); + + $unitIds = array_column($query->getArrayResult(), 'id'); + + // Contar clientes sin paginación + $qb = $entityManager->createQueryBuilder(); + $qb->select('COUNT(c.id)') + ->from('App\Entity\Client', 'c') + ->where('c.organizationalUnit IN (:unitIds)') + ->setParameter('unitIds', $unitIds); + + // Aplicar los mismos filtros que en `findClientsByOrganizationalUnitAndDescendants` + foreach ($filters as $key => $value) { + if ($key === 'order' || $key === 'page' || $key === 'itemsPerPage' || $key === 'organizationalUnit.id') { + continue; // No son filtros de búsqueda } if ($key === 'exists') { @@ -67,8 +143,9 @@ class ClientRepository extends AbstractRepository } } - return $qb->getQuery()->getResult(); + return (int) $qb->getQuery()->getSingleScalarResult(); } + } diff --git a/src/State/Provider/ClientProvider.php b/src/State/Provider/ClientProvider.php index a6b0fad..9e22d42 100644 --- a/src/State/Provider/ClientProvider.php +++ b/src/State/Provider/ClientProvider.php @@ -43,6 +43,8 @@ readonly class ClientProvider implements ProviderInterface if (isset($filters['organizationalUnit.id'])) { $organizationalUnitId = (int) $filters['organizationalUnit.id']; + + $totalClients = $this->clientRepository->countClientsByOrganizationalUnitAndDescendants($organizationalUnitId, $filters); $clients = $this->clientRepository->findClientsByOrganizationalUnitAndDescendants($organizationalUnitId, $filters); $items = new \ArrayObject(); @@ -50,7 +52,7 @@ readonly class ClientProvider implements ProviderInterface $items[] = new ClientOutput($client); } - return new TraversablePaginator($items, 1, count($clients), count($clients)); + return new TraversablePaginator($items, $filters['page'] ?? 1, $filters['itemsPerPage'] ?? count($clients), $totalClients); } else { $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); @@ -65,6 +67,7 @@ readonly class ClientProvider implements ProviderInterface + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null { $item = $this->itemProvider->provide($operation, $uriVariables, $context);