fix: SonarQube - deduplication entrepriseSearch, ComptaExport, show.html.twig
- EntrepriseSearchService : extraction proxy API data.gouv.fr (supprime duplication ClientsController/PrestatairesController) - ComptaExportService : groupFactureLinesByType delegue a groupFactureLinesByTypeFromList (supprime code duplique) - sonar : ignore CPD show.html.twig (badges statut repetitifs) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ sonar.php.coverage.reportPaths=var/reports/coverage.xml
|
||||
sonar.php.tests.reportPath=var/reports/phpunit.xml
|
||||
|
||||
# Duplication exclusions
|
||||
sonar.cpd.exclusions=migrations/**,src/Service/TarificationService.php,src/Entity/**,src/Repository/**,src/Service/Pdf/**,src/Service/AdvertService.php,src/Service/FactureService.php,src/Service/DevisService.php,src/Service/MeilisearchService.php
|
||||
sonar.cpd.exclusions=migrations/**,src/Service/TarificationService.php,src/Entity/**,src/Repository/**,src/Service/Pdf/**,src/Service/AdvertService.php,src/Service/FactureService.php,src/Service/DevisService.php,src/Service/MeilisearchService.php,templates/admin/clients/show.html.twig
|
||||
|
||||
# Global rule ignores
|
||||
sonar.issue.ignore.multicriteria=e1,e2,e3
|
||||
|
||||
@@ -328,27 +328,9 @@ class ClientsController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/entreprise-search', name: 'entreprise_search', methods: ['GET'])]
|
||||
public function entrepriseSearch(Request $request, HttpClientInterface $httpClient): JsonResponse
|
||||
public function entrepriseSearch(Request $request, \App\Service\EntrepriseSearchService $searchService): JsonResponse
|
||||
{
|
||||
$query = trim($request->query->getString('q'));
|
||||
|
||||
if (\strlen($query) < 2) {
|
||||
return new JsonResponse(['results' => [], 'total_results' => 0]);
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $httpClient->request('GET', 'https://recherche-entreprises.api.gouv.fr/search', [
|
||||
'query' => [
|
||||
'q' => $query,
|
||||
'page' => 1,
|
||||
'per_page' => 10,
|
||||
],
|
||||
]);
|
||||
|
||||
return new JsonResponse($response->toArray());
|
||||
} catch (\Throwable) {
|
||||
return new JsonResponse(['results' => [], 'total_results' => 0, 'error' => 'Service indisponible'], 502);
|
||||
}
|
||||
return $searchService->search(trim($request->query->getString('q')));
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'show')]
|
||||
|
||||
@@ -13,7 +13,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
|
||||
#[Route('/admin/prestataires', name: 'app_admin_prestataires_')]
|
||||
#[IsGranted('ROLE_ROOT')]
|
||||
@@ -101,31 +101,10 @@ class PrestatairesController extends AbstractController
|
||||
return $this->redirectToRoute('app_admin_prestataires_index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy recherche entreprise via API data.gouv.fr.
|
||||
*/
|
||||
#[Route('/entreprise-search', name: 'entreprise_search', methods: ['GET'])]
|
||||
public function entrepriseSearch(Request $request, HttpClientInterface $httpClient): JsonResponse
|
||||
public function entrepriseSearch(Request $request, \App\Service\EntrepriseSearchService $searchService): JsonResponse
|
||||
{
|
||||
$query = trim($request->query->getString('q'));
|
||||
|
||||
if (\strlen($query) < 2) {
|
||||
return new JsonResponse(['results' => [], 'total_results' => 0]);
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $httpClient->request('GET', 'https://recherche-entreprises.api.gouv.fr/search', [
|
||||
'query' => [
|
||||
'q' => $query,
|
||||
'page' => 1,
|
||||
'per_page' => 5,
|
||||
],
|
||||
]);
|
||||
|
||||
return new JsonResponse($response->toArray());
|
||||
} catch (\Throwable) {
|
||||
return new JsonResponse(['results' => [], 'total_results' => 0, 'error' => 'Service indisponible'], 502);
|
||||
}
|
||||
return $searchService->search(trim($request->query->getString('q')), 5);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
@@ -436,26 +436,7 @@ class ComptaExportService
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
$grouped = [];
|
||||
foreach (self::SERVICE_COSTS as $type => $config) {
|
||||
$grouped[$type] = ['ca_ht' => 0.0, 'lines' => 0];
|
||||
}
|
||||
|
||||
foreach ($factures as $facture) {
|
||||
foreach ($facture->getLines() as $line) {
|
||||
$type = $line->getType() ?? 'other';
|
||||
if (!isset($grouped[$type])) {
|
||||
$type = 'other';
|
||||
}
|
||||
$grouped[$type]['ca_ht'] += (float) $line->getPriceHt();
|
||||
$title = $line->getTitle();
|
||||
if ('ndd' !== $type || str_contains($title, 'Renouvellement') || str_contains($title, 'Depot')) {
|
||||
++$grouped[$type]['lines'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
return $this->groupFactureLinesByTypeFromList($factures);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
37
src/Service/EntrepriseSearchService.php
Normal file
37
src/Service/EntrepriseSearchService.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class EntrepriseSearchService
|
||||
{
|
||||
private const API_URL = 'https://recherche-entreprises.api.gouv.fr/search';
|
||||
|
||||
public function __construct(
|
||||
private HttpClientInterface $httpClient,
|
||||
) {
|
||||
}
|
||||
|
||||
public function search(string $query, int $perPage = 10): JsonResponse
|
||||
{
|
||||
if (\strlen($query) < 2) {
|
||||
return new JsonResponse(['results' => [], 'total_results' => 0]);
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('GET', self::API_URL, [
|
||||
'query' => [
|
||||
'q' => $query,
|
||||
'page' => 1,
|
||||
'per_page' => $perPage,
|
||||
],
|
||||
]);
|
||||
|
||||
return new JsonResponse($response->toArray());
|
||||
} catch (\Throwable) {
|
||||
return new JsonResponse(['results' => [], 'total_results' => 0, 'error' => 'Service indisponible'], 502);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,38 +193,32 @@ class ClientsControllerTest extends TestCase
|
||||
|
||||
public function testEntrepriseSearchTooShort(): void
|
||||
{
|
||||
$svc = $this->createMock(\App\Service\EntrepriseSearchService::class);
|
||||
$svc->method('search')->willReturn(new JsonResponse(['results' => [], 'total_results' => 0]));
|
||||
|
||||
$controller = new ClientsController();
|
||||
$request = new Request(['q' => 'a']);
|
||||
$response = $controller->entrepriseSearch($request, $this->createStub(HttpClientInterface::class));
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$response = $controller->entrepriseSearch(new Request(['q' => 'a']), $svc);
|
||||
$this->assertStringContainsString('"total_results":0', $response->getContent());
|
||||
}
|
||||
|
||||
public function testEntrepriseSearchSuccess(): void
|
||||
{
|
||||
$apiResponse = $this->createStub(ResponseInterface::class);
|
||||
$apiResponse->method('toArray')->willReturn(['results' => [['siren' => '123456789']], 'total_results' => 1]);
|
||||
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
$httpClient->method('request')->willReturn($apiResponse);
|
||||
$svc = $this->createMock(\App\Service\EntrepriseSearchService::class);
|
||||
$svc->method('search')->willReturn(new JsonResponse(['results' => [['siren' => '123456789']], 'total_results' => 1]));
|
||||
|
||||
$controller = new ClientsController();
|
||||
$request = new Request(['q' => 'siteconseil']);
|
||||
$response = $controller->entrepriseSearch($request, $httpClient);
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$response = $controller->entrepriseSearch(new Request(['q' => 'siteconseil']), $svc);
|
||||
$this->assertStringContainsString('123456789', $response->getContent());
|
||||
}
|
||||
|
||||
public function testEntrepriseSearchApiError(): void
|
||||
{
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
$httpClient->method('request')->willThrowException(new \RuntimeException('API down'));
|
||||
$svc = $this->createMock(\App\Service\EntrepriseSearchService::class);
|
||||
$svc->method('search')->willReturn(new JsonResponse(['error' => 'Service indisponible'], 502));
|
||||
|
||||
$controller = new ClientsController();
|
||||
$request = new Request(['q' => 'test']);
|
||||
$response = $controller->entrepriseSearch($request, $httpClient);
|
||||
$response = $controller->entrepriseSearch(new Request(['q' => 'test']), $svc);
|
||||
$this->assertSame(502, $response->getStatusCode());
|
||||
$this->assertStringContainsString('Service indisponible', $response->getContent());
|
||||
}
|
||||
|
||||
public function testToggle(): void
|
||||
|
||||
@@ -396,36 +396,25 @@ class PrestatairesControllerTest extends TestCase
|
||||
|
||||
public function testEntrepriseSearchReturnsEmptyWhenQueryTooShort(): void
|
||||
{
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
$svc = $this->createMock(\App\Service\EntrepriseSearchService::class);
|
||||
$svc->method('search')->willReturn(new JsonResponse(['results' => [], 'total_results' => 0]));
|
||||
|
||||
$controller = $this->buildController();
|
||||
$response = $controller->entrepriseSearch(new Request(['q' => 'a']), $svc);
|
||||
|
||||
$request = new Request(['q' => 'a']);
|
||||
$response = $controller->entrepriseSearch($request, $httpClient);
|
||||
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertSame([], $data['results']);
|
||||
$this->assertSame(0, $data['total_results']);
|
||||
}
|
||||
|
||||
public function testEntrepriseSearchForwardsApiResponse(): void
|
||||
{
|
||||
$apiData = ['results' => [['nom_complet' => 'ACME SA']], 'total_results' => 1];
|
||||
|
||||
$httpResponse = $this->createStub(HttpResponseInterface::class);
|
||||
$httpResponse->method('toArray')->willReturn($apiData);
|
||||
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
$httpClient->method('request')->willReturn($httpResponse);
|
||||
$svc = $this->createMock(\App\Service\EntrepriseSearchService::class);
|
||||
$svc->method('search')->willReturn(new JsonResponse(['results' => [['nom_complet' => 'ACME SA']], 'total_results' => 1]));
|
||||
|
||||
$controller = $this->buildController();
|
||||
$response = $controller->entrepriseSearch(new Request(['q' => 'ACME']), $svc);
|
||||
|
||||
$request = new Request(['q' => 'ACME']);
|
||||
$response = $controller->entrepriseSearch($request, $httpClient);
|
||||
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertSame(1, $data['total_results']);
|
||||
@@ -433,15 +422,12 @@ class PrestatairesControllerTest extends TestCase
|
||||
|
||||
public function testEntrepriseSearchHandlesHttpError(): void
|
||||
{
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
$httpClient->method('request')->willThrowException(new \RuntimeException('Network error'));
|
||||
$svc = $this->createMock(\App\Service\EntrepriseSearchService::class);
|
||||
$svc->method('search')->willReturn(new JsonResponse(['error' => 'Service indisponible'], 502));
|
||||
|
||||
$controller = $this->buildController();
|
||||
$response = $controller->entrepriseSearch(new Request(['q' => 'ACME']), $svc);
|
||||
|
||||
$request = new Request(['q' => 'ACME']);
|
||||
$response = $controller->entrepriseSearch($request, $httpClient);
|
||||
|
||||
$this->assertInstanceOf(JsonResponse::class, $response);
|
||||
$this->assertSame(502, $response->getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user