fix: SonarQube - extraction ComptaExportService + constantes + CC reduite

ComptaExportService (nouveau service) :
- 14 methodes extraites du ComptabiliteController (29->14 methodes)
- Constantes : LABEL_JOURNAL_VENTES, LABEL_GRAND_LIVRE,
  LABEL_COMMISSIONS_STRIPE, DATE_FORMAT_FR, DQL_BETWEEN_DATES,
  DQL_IS_PAID, LABEL_CLIENT_DELETED, PREFIX_FACTURE
- resolveCustomerInfo() helper pour deduplication
- groupFactureLinesByType, getServiceGroups, aggregateServiceGroup,
  appendPrestataireRows, resolveStatutRentabilite pour CC reduction
- resolveTrancheAge via array lookup (4 returns -> 2)

ComptabiliteController :
- 14 methodes (etait 29), sous la limite de 20
- signCallback CC 25->~10 : extraction downloadSignedDocuments + sendSignedDocumentEmail
- rapportFinancier CC 22->~12 : extraction computeRecettes + computeDepenses
- Suppression $tvaEnabled (deplace dans service)
- CONTENT_DISPOSITION_PREFIX constante

ClientsController :
- 20 methodes : fusion removeContact inline dans handleContactForm
- persistNewContact extrait pour CC reduction

PHPStan level 6 : 0 erreur
PHP CS Fixer : 0 fichier modifie

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-08 10:19:16 +02:00
parent b337622673
commit 92bf777597
4 changed files with 973 additions and 827 deletions

View File

@@ -4,6 +4,7 @@ namespace App\Tests\Controller\Admin;
use App\Controller\Admin\ComptabiliteController;
use App\Entity\User;
use App\Service\ComptaExportService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
@@ -60,15 +61,26 @@ class ComptabiliteControllerTest extends TestCase
return $kernel;
}
private function buildExportService(?EntityManagerInterface $em = null): ComptaExportService
{
return new ComptaExportService($em ?? $this->buildEmWithQueryBuilder(), false);
}
private function buildExportServiceWithTva(?EntityManagerInterface $em = null): ComptaExportService
{
return new ComptaExportService($em ?? $this->buildEmWithQueryBuilder(), true);
}
/**
* Build a controller wired with a user token and a router that returns non-empty paths.
* Required for methods that call getUser() and generateUrl()/redirectToRoute().
*/
private function buildSignController(): \App\Controller\Admin\ComptabiliteController
private function buildSignController(?ComptaExportService $exportService = null): \App\Controller\Admin\ComptabiliteController
{
$em = $this->buildEmWithQueryBuilder();
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, false, 'http://docuseal.example');
$svc = $exportService ?? $this->buildExportService($em);
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, 'http://docuseal.example', $svc);
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(RequestStack::class);
@@ -113,12 +125,13 @@ class ComptabiliteControllerTest extends TestCase
return $controller;
}
private function buildController(): ComptabiliteController
private function buildController(?ComptaExportService $exportService = null): ComptabiliteController
{
$em = $this->buildEmWithQueryBuilder();
$kernel = $this->buildKernel();
$svc = $exportService ?? $this->buildExportService($em);
$controller = new ComptabiliteController($em, $kernel, false, 'http://docuseal.example');
$controller = new ComptabiliteController($em, $kernel, 'http://docuseal.example', $svc);
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(RequestStack::class);
@@ -536,11 +549,12 @@ class ComptabiliteControllerTest extends TestCase
return $facture;
}
private function buildControllerWithData(array $emData): \App\Controller\Admin\ComptabiliteController
private function buildControllerWithData(array $emData, array $otherData = []): \App\Controller\Admin\ComptabiliteController
{
$em = $this->buildEmWithData($emData);
$em = !empty($otherData) ? $this->buildEmWithData($emData, $otherData) : $this->buildEmWithData($emData);
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, false, 'http://docuseal.example');
$svc = new ComptaExportService($em, false);
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, 'http://docuseal.example', $svc);
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(\Symfony\Component\HttpFoundation\RequestStack::class);
@@ -575,23 +589,12 @@ class ComptabiliteControllerTest extends TestCase
return $controller;
}
public function testExportJournalVentesWithPaidFacture(): void
private function buildControllerWithTvaAndData(array $emData): \App\Controller\Admin\ComptabiliteController
{
$facture = $this->buildPaidFacture();
$controller = $this->buildControllerWithData([$facture]);
$request = new Request(['period' => 'current', 'format' => 'csv']);
$response = $controller->exportJournalVentes($request);
$this->assertSame(200, $response->getStatusCode());
$this->assertStringContainsString('text/csv', $response->headers->get('Content-Type') ?? '');
}
public function testExportJournalVentesWithTvaEnabled(): void
{
$facture = $this->buildPaidFacture();
$em = $this->buildEmWithData([$facture]);
$em = $this->buildEmWithData($emData);
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, true, 'http://docuseal.example');
$svc = new ComptaExportService($em, true);
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, 'http://docuseal.example', $svc);
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(\Symfony\Component\HttpFoundation\RequestStack::class);
@@ -610,6 +613,25 @@ class ComptabiliteControllerTest extends TestCase
]);
$controller->setContainer($container);
return $controller;
}
public function testExportJournalVentesWithPaidFacture(): void
{
$facture = $this->buildPaidFacture();
$controller = $this->buildControllerWithData([$facture]);
$request = new Request(['period' => 'current', 'format' => 'csv']);
$response = $controller->exportJournalVentes($request);
$this->assertSame(200, $response->getStatusCode());
$this->assertStringContainsString('text/csv', $response->headers->get('Content-Type') ?? '');
}
public function testExportJournalVentesWithTvaEnabled(): void
{
$facture = $this->buildPaidFacture();
$controller = $this->buildControllerWithTvaAndData([$facture]);
$request = new Request(['period' => 'current', 'format' => 'json']);
$response = $controller->exportJournalVentes($request);
$this->assertSame(200, $response->getStatusCode());
@@ -760,7 +782,8 @@ class ComptabiliteControllerTest extends TestCase
$em->method('createQueryBuilder')->willReturn($qb);
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, false, 'http://docuseal.example');
$svc = new ComptaExportService($em, false);
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, 'http://docuseal.example', $svc);
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(\Symfony\Component\HttpFoundation\RequestStack::class);
@@ -1030,27 +1053,7 @@ class ComptabiliteControllerTest extends TestCase
$facture->setPaidAt(new \DateTimeImmutable('2026-04-01'));
$facture->setPaidMethod('sepa');
$em = $this->buildEmWithData([$facture]);
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, true, 'http://docuseal.example');
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(\Symfony\Component\HttpFoundation\RequestStack::class);
$stack->method('getSession')->willReturn($session);
$twig = $this->createStub(\Twig\Environment::class);
$twig->method('render')->willReturn('<html></html>');
$container = $this->createStub(\Psr\Container\ContainerInterface::class);
$container->method('has')->willReturn(false);
$container->method('get')->willReturnMap([
['twig', $twig],
['router', $this->createStub(\Symfony\Component\Routing\RouterInterface::class)],
['security.authorization_checker', $this->createStub(\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface::class)],
['security.token_storage', $this->createStub(\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface::class)],
['request_stack', $stack],
['parameter_bag', $this->createStub(\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface::class)],
]);
$controller->setContainer($container);
$controller = $this->buildControllerWithTvaAndData([$facture]);
$request = new Request(['period' => 'current', 'format' => 'csv']);
$response = $controller->exportFec($request);
@@ -1332,27 +1335,7 @@ class ComptabiliteControllerTest extends TestCase
$facture->setMontantTtc('600.00');
// EM returns [] for factures query (1st), then [$facture] for facturesPresta (2nd)
$em = $this->buildEmWithData([], [$facture]);
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, false, 'http://docuseal.example');
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(\Symfony\Component\HttpFoundation\RequestStack::class);
$stack->method('getSession')->willReturn($session);
$twig = $this->createStub(\Twig\Environment::class);
$twig->method('render')->willReturn('<html></html>');
$container = $this->createStub(\Psr\Container\ContainerInterface::class);
$container->method('has')->willReturn(false);
$container->method('get')->willReturnMap([
['twig', $twig],
['router', $this->createStub(\Symfony\Component\Routing\RouterInterface::class)],
['security.authorization_checker', $this->createStub(\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface::class)],
['security.token_storage', $this->createStub(\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface::class)],
['request_stack', $stack],
['parameter_bag', $this->createStub(\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface::class)],
]);
$controller->setContainer($container);
$controller = $this->buildControllerWithData([], [$facture]);
$request = new Request(['period' => 'current', 'format' => 'json']);
$response = $controller->exportCoutsServices($request);
@@ -1414,7 +1397,8 @@ class ComptabiliteControllerTest extends TestCase
$em->method('createQueryBuilder')->willReturn($qb);
$kernel = $this->buildKernel();
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, false, 'http://docuseal.example');
$svc = new ComptaExportService($em, false);
$controller = new \App\Controller\Admin\ComptabiliteController($em, $kernel, 'http://docuseal.example', $svc);
$session = new Session(new MockArraySessionStorage());
$stack = $this->createStub(\Symfony\Component\HttpFoundation\RequestStack::class);