feat(transport) : endpoint recherche QualimatCarrier (ERP-156)
GET /api/qualimat_carriers?search= pour la saisie assistee du nom (RG-4.01, spec-back § 4.7) : recherche fuzzy sur name (+ siret), restreinte aux lignes actives (is_active = true), triee name ASC, paginee (regle n°13). - QualimatCarrierRepositoryInterface + DoctrineQualimatCarrierRepository : QueryBuilder de recherche (forcage is_active cote serveur, fuzzy multi-champs). - QualimatCarrierSearchProvider : provider de la GetCollection (pagination Hydra + echappatoire ?pagination=false), branche uniquement sur la collection. - ApiResource : provider custom sur GetCollection, retrait des ApiFilter natifs (incapables d'unifier name/siret sous ?search= ni d'imposer l'actif). Mapping ORM inchange (schema:update reste no-op). Aucune ecriture exposee. - Tests : actifs seuls, tri name, match siret, pagination Hydra, 403 sans perm.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Transport\Infrastructure\Doctrine;
|
||||
|
||||
use App\Module\Transport\Domain\Entity\QualimatCarrier;
|
||||
use App\Module\Transport\Domain\Repository\QualimatCarrierRepositoryInterface;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<QualimatCarrier>
|
||||
*/
|
||||
class DoctrineQualimatCarrierRepository extends ServiceEntityRepository implements QualimatCarrierRepositoryInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, QualimatCarrier::class);
|
||||
}
|
||||
|
||||
public function createSearchQueryBuilder(?string $search = null): QueryBuilder
|
||||
{
|
||||
// Saisie assistee (§ 4.7) : on ne propose QUE des transporteurs QUALIMAT
|
||||
// actifs (is_active = true), tries par nom. Le forcage de l'actif est une
|
||||
// regle serveur (pas un filtre client) — les lignes soft-deletees par la
|
||||
// synchro restent invisibles.
|
||||
$qb = $this->createQueryBuilder('q')
|
||||
->andWhere('q.isActive = true')
|
||||
->orderBy('q.name', 'ASC')
|
||||
;
|
||||
|
||||
$this->applySearch($qb, $search);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recherche fuzzy insensible a la casse sur le nom (+ siret) du transporteur
|
||||
* QUALIMAT (§ 4.7 / RG-4.01). Metacaracteres LIKE (%, _, \) echappes pour
|
||||
* rester litteraux.
|
||||
*/
|
||||
private function applySearch(QueryBuilder $qb, ?string $search): void
|
||||
{
|
||||
if (null === $search || '' === trim($search)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$escaped = str_replace(['\\', '%', '_'], ['\\\\', '\%', '\_'], trim($search));
|
||||
$pattern = '%'.mb_strtolower($escaped, 'UTF-8').'%';
|
||||
|
||||
$qb->andWhere('LOWER(q.name) LIKE :search OR LOWER(q.siret) LIKE :search')
|
||||
->setParameter('search', $pattern)
|
||||
;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user