Entites (76 tests) : - PrestataireTest : constructeur, setters, getFullAddress, getTotalPaidHt - FacturePrestataireTest : constructeur, getPeriodLabel 12 mois, Vich upload - AdvertPaymentTest : constructeur, types constants, method - AdvertEventTest : constructeur, getTypeLabel, 5 types + fallback - FactureLineTest : constructeur, setters, optionnels nullable - ActionLogTest : constructeur, 10 action constants, severity - PaymentReminderTest : 8 steps, getStepLabel, getSeverity - DocusealEventTest : constructeur, nullable fields Commands (16 tests) : - ReminderFacturesPrestataireCommandTest : 6 scenarios (aucun presta, tous OK, factures manquantes, SIRET vide, mois different) - PaymentReminderCommandTest : 10 scenarios (skip recent, J+15 emails, suspension, termination, exception handling) Services PDF (24 tests) : - ComptaPdfTest : empty/FEC/multi-page, totaux Debit/Credit - RapportFinancierPdfTest : recettes/depenses, bilan equilibre/deficit/excedent - FacturePdfTest : lignes, TVA, customer address, paid badge, multi-page Controllers (47 tests) : - ComptabiliteControllerTest : 18 tests (index, 7 exports CSV, 2 JSON, 4 PDF, 2 rapport financier) - PrestatairesControllerTest : 19 tests (CRUD, factures, SIRET proxy) - FactureControllerTest : 6 tests (search, send) - FactureVerifyControllerTest : 4 tests (HMAC valid/invalid/not found) Couverture : 51%->60% classes, 58%->73% methodes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
200 lines
7.0 KiB
PHP
200 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Command;
|
|
|
|
use App\Command\ReminderFacturesPrestataireCommand;
|
|
use App\Entity\FacturePrestataire;
|
|
use App\Entity\Prestataire;
|
|
use App\Service\MailerService;
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Doctrine\ORM\EntityRepository;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\Console\Tester\CommandTester;
|
|
|
|
class ReminderFacturesPrestataireCommandTest extends TestCase
|
|
{
|
|
private EntityManagerInterface $em;
|
|
private MailerService $mailer;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
|
$this->mailer = $this->createMock(MailerService::class);
|
|
}
|
|
|
|
private function makePrestataire(string $raisonSociale, ?string $siret = null): Prestataire
|
|
{
|
|
$p = new Prestataire($raisonSociale);
|
|
if (null !== $siret) {
|
|
$p->setSiret($siret);
|
|
}
|
|
|
|
return $p;
|
|
}
|
|
|
|
private function makeFacturePrestataire(int $year, int $month): FacturePrestataire
|
|
{
|
|
$f = $this->createStub(FacturePrestataire::class);
|
|
$f->method('getYear')->willReturn($year);
|
|
$f->method('getMonth')->willReturn($month);
|
|
|
|
return $f;
|
|
}
|
|
|
|
private function stubRepository(array $prestataires): void
|
|
{
|
|
$repo = $this->createStub(EntityRepository::class);
|
|
$repo->method('findBy')->willReturn($prestataires);
|
|
|
|
$this->em->method('getRepository')
|
|
->with(Prestataire::class)
|
|
->willReturn($repo);
|
|
}
|
|
|
|
public function testNoActivePrestatairesReturnsSuccess(): void
|
|
{
|
|
$this->stubRepository([]);
|
|
|
|
$this->mailer->expects($this->never())->method('sendEmail');
|
|
|
|
$command = new ReminderFacturesPrestataireCommand($this->em, $this->mailer);
|
|
$tester = new CommandTester($command);
|
|
$tester->execute([]);
|
|
|
|
$this->assertSame(0, $tester->getStatusCode());
|
|
$this->assertStringContainsString('Toutes les factures prestataires', $tester->getDisplay());
|
|
}
|
|
|
|
public function testAllPrestatairesHaveFactureForPreviousMonth(): void
|
|
{
|
|
$now = new \DateTimeImmutable();
|
|
$prev = $now->modify('first day of last month');
|
|
$year = (int) $prev->format('Y');
|
|
$month = (int) $prev->format('n');
|
|
|
|
$presta = $this->makePrestataire('ACME Corp', '12345678900011');
|
|
$facture = $this->makeFacturePrestataire($year, $month);
|
|
$presta->getFactures()->add($facture);
|
|
|
|
$this->stubRepository([$presta]);
|
|
|
|
$this->mailer->expects($this->never())->method('sendEmail');
|
|
|
|
$command = new ReminderFacturesPrestataireCommand($this->em, $this->mailer);
|
|
$tester = new CommandTester($command);
|
|
$tester->execute([]);
|
|
|
|
$this->assertSame(0, $tester->getStatusCode());
|
|
$this->assertStringContainsString('Toutes les factures prestataires', $tester->getDisplay());
|
|
}
|
|
|
|
public function testMissingFacturesSendsReminderEmail(): void
|
|
{
|
|
$presta1 = $this->makePrestataire('ACME Corp', '12345678900011');
|
|
$presta2 = $this->makePrestataire('Beta SARL');
|
|
|
|
// presta1 has no factures for the previous month, presta2 has none at all
|
|
$this->stubRepository([$presta1, $presta2]);
|
|
|
|
$this->mailer->expects($this->once())
|
|
->method('getAdminEmail')
|
|
->willReturn('admin@e-cosplay.fr');
|
|
|
|
$this->mailer->expects($this->once())
|
|
->method('sendEmail')
|
|
->with(
|
|
'admin@e-cosplay.fr',
|
|
$this->stringContains('Rappel : factures prestataires'),
|
|
$this->stringContains('ACME Corp'),
|
|
null,
|
|
null,
|
|
false,
|
|
);
|
|
|
|
$command = new ReminderFacturesPrestataireCommand($this->em, $this->mailer);
|
|
$tester = new CommandTester($command);
|
|
$tester->execute([]);
|
|
|
|
$this->assertSame(0, $tester->getStatusCode());
|
|
$display = $tester->getDisplay();
|
|
$this->assertStringContainsString('2 facture(s) prestataire(s) manquante(s)', $display);
|
|
$this->assertStringContainsString('rappel envoye', $display);
|
|
}
|
|
|
|
public function testPrestataireWithFactureForDifferentMonthStillMissing(): void
|
|
{
|
|
$now = new \DateTimeImmutable();
|
|
$prev = $now->modify('first day of last month');
|
|
$year = (int) $prev->format('Y');
|
|
$month = (int) $prev->format('n');
|
|
|
|
// Facture for a different month (two months ago)
|
|
$wrongMonth = $month === 1 ? 12 : $month - 1;
|
|
$wrongYear = $month === 1 ? $year - 1 : $year;
|
|
|
|
$presta = $this->makePrestataire('Old Corp', '99999999900011');
|
|
$oldFacture = $this->makeFacturePrestataire($wrongYear, $wrongMonth);
|
|
$presta->getFactures()->add($oldFacture);
|
|
|
|
$this->stubRepository([$presta]);
|
|
|
|
$this->mailer->method('getAdminEmail')->willReturn('admin@e-cosplay.fr');
|
|
$this->mailer->expects($this->once())->method('sendEmail');
|
|
|
|
$command = new ReminderFacturesPrestataireCommand($this->em, $this->mailer);
|
|
$tester = new CommandTester($command);
|
|
$tester->execute([]);
|
|
|
|
$this->assertSame(0, $tester->getStatusCode());
|
|
$this->assertStringContainsString('1 facture(s) prestataire(s) manquante(s)', $tester->getDisplay());
|
|
}
|
|
|
|
public function testEmailContainsPrestataireDetails(): void
|
|
{
|
|
$presta = $this->makePrestataire('Dupont & Cie', '11122233300011');
|
|
|
|
$this->stubRepository([$presta]);
|
|
|
|
$this->mailer->method('getAdminEmail')->willReturn('admin@e-cosplay.fr');
|
|
|
|
$capturedHtml = null;
|
|
$this->mailer->method('sendEmail')
|
|
->willReturnCallback(function (string $to, string $subject, string $html) use (&$capturedHtml) {
|
|
$capturedHtml = $html;
|
|
});
|
|
|
|
$command = new ReminderFacturesPrestataireCommand($this->em, $this->mailer);
|
|
$tester = new CommandTester($command);
|
|
$tester->execute([]);
|
|
|
|
$this->assertNotNull($capturedHtml);
|
|
$this->assertStringContainsString('Dupont & Cie', $capturedHtml);
|
|
$this->assertStringContainsString('11122233300011', $capturedHtml);
|
|
$this->assertStringContainsString('crm.e-cosplay.fr/admin/prestataires', $capturedHtml);
|
|
}
|
|
|
|
public function testPrestataireWithoutSiretSendsEmailWithoutSiret(): void
|
|
{
|
|
$presta = $this->makePrestataire('Anonymous Corp');
|
|
|
|
$this->stubRepository([$presta]);
|
|
|
|
$this->mailer->method('getAdminEmail')->willReturn('admin@e-cosplay.fr');
|
|
|
|
$capturedHtml = null;
|
|
$this->mailer->method('sendEmail')
|
|
->willReturnCallback(function (string $to, string $subject, string $html) use (&$capturedHtml) {
|
|
$capturedHtml = $html;
|
|
});
|
|
|
|
$command = new ReminderFacturesPrestataireCommand($this->em, $this->mailer);
|
|
$tester = new CommandTester($command);
|
|
$tester->execute([]);
|
|
|
|
$this->assertSame(0, $tester->getStatusCode());
|
|
$this->assertNotNull($capturedHtml);
|
|
$this->assertStringContainsString('Anonymous Corp', $capturedHtml);
|
|
}
|
|
}
|