Entites completes a 100% : - AdvertLineTest : 12 tests (constructor, setters, fluent interface) - DevisLineTest : 12 tests (idem) Services ameliores vers 100% : - DocuSealServiceTest : +1 (getLogoBase64 avec logo.jpg) - FactureServiceTest : +1 (createFromAdvert avec lines description/type) - MailerServiceTest : +1 (injectAttachmentsList sans <tr> avant footer) - OrderNumberServiceTest : +4 (generate/preview create new number) - ComptaPdfTest : +2 (Header/Footer explicites, setData re-assign) - FacturePdfTest : +3 (displayHmac, appendRib sans/avec fichier) Controllers ameliores : - ComptabiliteControllerTest : +22 (tous exports avec donnees, TVA, sign) - StatsControllerTest : +8 (factures payees, AdvertPayment, services, resolveStatus) - ClientsControllerTest : +12 (contacts, NDD, securite, DNS check) - WebhookStripeControllerTest : +8 (handlePaymentSucceeded/Failed tous chemins) - AdminControllersTest : +1 (dashboard globalSearch empty) - FactureControllerTest : +2 (customer null, generatePdf 404) - PrestatairesControllerTest : +1 (deleteFacture mismatch) - SyncControllerTest : +1 (syncAll error) - TarificationControllerTest : +1 (purge avec stripeId) - LegalControllerTest : +3 (rgpdVerify access/deletion/missing params) Progression : 83% -> 87% methodes, 18 -> 10 classes restantes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
269 lines
10 KiB
PHP
269 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Service;
|
|
|
|
use App\Entity\Advert;
|
|
use App\Entity\Facture;
|
|
use App\Entity\OrderNumber;
|
|
use App\Service\FactureService;
|
|
use App\Service\OrderNumberService;
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class FactureServiceTest extends TestCase
|
|
{
|
|
private const HMAC_SECRET = 'test-hmac-secret';
|
|
|
|
public function testCreateWithoutAdvert(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00001');
|
|
$orderNumber->markAsUsed();
|
|
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
$orderService->method('generateAndUse')->willReturn($orderNumber);
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->create();
|
|
|
|
$this->assertInstanceOf(Facture::class, $facture);
|
|
$this->assertSame($orderNumber, $facture->getOrderNumber());
|
|
$this->assertNull($facture->getAdvert());
|
|
}
|
|
|
|
public function testCreateFromAdvertFirstFacture(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00002');
|
|
|
|
$advert = $this->createStub(Advert::class);
|
|
$advert->method('getOrderNumber')->willReturn($orderNumber);
|
|
$advert->method('getFactures')->willReturn(new ArrayCollection());
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->create($advert);
|
|
|
|
$this->assertInstanceOf(Facture::class, $facture);
|
|
$this->assertSame(0, $facture->getSplitIndex());
|
|
}
|
|
|
|
public function testCreateFromAdvertSecondFacture(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00003');
|
|
|
|
$firstFacture = new Facture($orderNumber, self::HMAC_SECRET);
|
|
|
|
$advert = $this->createStub(Advert::class);
|
|
$advert->method('getOrderNumber')->willReturn($orderNumber);
|
|
$advert->method('getFactures')->willReturn(new ArrayCollection([$firstFacture]));
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->create($advert);
|
|
|
|
$this->assertSame(2, $facture->getSplitIndex());
|
|
$this->assertSame(1, $firstFacture->getSplitIndex());
|
|
}
|
|
|
|
public function testCreateFromAdvertThirdFacture(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00004');
|
|
|
|
$f1 = new Facture($orderNumber, self::HMAC_SECRET);
|
|
$f1->setSplitIndex(1);
|
|
$f2 = new Facture($orderNumber, self::HMAC_SECRET);
|
|
$f2->setSplitIndex(2);
|
|
|
|
$advert = $this->createStub(Advert::class);
|
|
$advert->method('getOrderNumber')->willReturn($orderNumber);
|
|
$advert->method('getFactures')->willReturn(new ArrayCollection([$f1, $f2]));
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->create($advert);
|
|
|
|
$this->assertSame(3, $facture->getSplitIndex());
|
|
}
|
|
|
|
public function testCreateFromAdvertDirectCall(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00005');
|
|
|
|
$advert = $this->createStub(Advert::class);
|
|
$advert->method('getOrderNumber')->willReturn($orderNumber);
|
|
$advert->method('getFactures')->willReturn(new ArrayCollection());
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->createFromAdvert($advert);
|
|
|
|
$this->assertInstanceOf(Facture::class, $facture);
|
|
}
|
|
|
|
// --- isTvaEnabled ---
|
|
|
|
public function testIsTvaEnabledReturnsTrueForTrueString(): void
|
|
{
|
|
$service = new FactureService(
|
|
$this->createStub(OrderNumberService::class),
|
|
$this->createStub(EntityManagerInterface::class),
|
|
$this->createStub(\Psr\Log\LoggerInterface::class),
|
|
self::HMAC_SECRET,
|
|
'true'
|
|
);
|
|
$this->assertTrue($service->isTvaEnabled());
|
|
}
|
|
|
|
public function testIsTvaEnabledReturnsTrueForOne(): void
|
|
{
|
|
$service = new FactureService(
|
|
$this->createStub(OrderNumberService::class),
|
|
$this->createStub(EntityManagerInterface::class),
|
|
$this->createStub(\Psr\Log\LoggerInterface::class),
|
|
self::HMAC_SECRET,
|
|
'1'
|
|
);
|
|
$this->assertTrue($service->isTvaEnabled());
|
|
}
|
|
|
|
public function testIsTvaEnabledReturnsFalseByDefault(): void
|
|
{
|
|
$service = new FactureService(
|
|
$this->createStub(OrderNumberService::class),
|
|
$this->createStub(EntityManagerInterface::class),
|
|
$this->createStub(\Psr\Log\LoggerInterface::class),
|
|
self::HMAC_SECRET
|
|
);
|
|
$this->assertFalse($service->isTvaEnabled());
|
|
}
|
|
|
|
// --- getTvaRate ---
|
|
|
|
public function testGetTvaRateReturnsFloat(): void
|
|
{
|
|
$service = new FactureService(
|
|
$this->createStub(OrderNumberService::class),
|
|
$this->createStub(EntityManagerInterface::class),
|
|
$this->createStub(\Psr\Log\LoggerInterface::class),
|
|
self::HMAC_SECRET,
|
|
'false',
|
|
'0.20'
|
|
);
|
|
$this->assertSame(0.20, $service->getTvaRate());
|
|
}
|
|
|
|
// --- computeTotals ---
|
|
|
|
public function testComputeTotalsTvaDisabled(): void
|
|
{
|
|
$service = new FactureService(
|
|
$this->createStub(OrderNumberService::class),
|
|
$this->createStub(EntityManagerInterface::class),
|
|
$this->createStub(\Psr\Log\LoggerInterface::class),
|
|
self::HMAC_SECRET,
|
|
'false',
|
|
'0.20'
|
|
);
|
|
$result = $service->computeTotals('150.00');
|
|
|
|
$this->assertSame('150.00', $result['totalHt']);
|
|
$this->assertSame('0.00', $result['totalTva']);
|
|
$this->assertSame('150.00', $result['totalTtc']);
|
|
}
|
|
|
|
public function testComputeTotalsTvaEnabled(): void
|
|
{
|
|
$service = new FactureService(
|
|
$this->createStub(OrderNumberService::class),
|
|
$this->createStub(EntityManagerInterface::class),
|
|
$this->createStub(\Psr\Log\LoggerInterface::class),
|
|
self::HMAC_SECRET,
|
|
'true',
|
|
'0.20'
|
|
);
|
|
$result = $service->computeTotals('100.00');
|
|
|
|
$this->assertSame('100.00', $result['totalHt']);
|
|
$this->assertSame('20.00', $result['totalTva']);
|
|
$this->assertSame('120.00', $result['totalTtc']);
|
|
}
|
|
|
|
// --- createPaidFactureFromAdvert ---
|
|
|
|
public function testCreatePaidFactureFromAdvertSuccess(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00010');
|
|
|
|
$advert = $this->createStub(Advert::class);
|
|
$advert->method('getOrderNumber')->willReturn($orderNumber);
|
|
$advert->method('getFactures')->willReturn(new ArrayCollection());
|
|
$advert->method('getTotalTtc')->willReturn('200.00');
|
|
$advert->method('getLines')->willReturn(new ArrayCollection());
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->createPaidFactureFromAdvert($advert, '200.00', 'Virement');
|
|
|
|
$this->assertInstanceOf(Facture::class, $facture);
|
|
$this->assertTrue($facture->isPaid());
|
|
$this->assertSame('Virement', $facture->getPaidMethod());
|
|
$this->assertSame(Facture::STATE_PAID, $facture->getState());
|
|
}
|
|
|
|
public function testCreatePaidFactureFromAdvertAmountMismatch(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00011');
|
|
|
|
$advert = $this->createStub(Advert::class);
|
|
$advert->method('getOrderNumber')->willReturn($orderNumber);
|
|
$advert->method('getTotalTtc')->willReturn('200.00');
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->createPaidFactureFromAdvert($advert, '150.00', 'CB');
|
|
|
|
$this->assertNull($facture);
|
|
}
|
|
|
|
public function testCreateFromAdvertCopiesLinesWithDescriptionTypeServiceId(): void
|
|
{
|
|
$orderNumber = new OrderNumber('04/2026-00020');
|
|
|
|
// Build real AdvertLines with description/type/serviceId so createFromAdvert copies them
|
|
$advert = new \App\Entity\Advert($orderNumber, 'secret');
|
|
|
|
$line1 = new \App\Entity\AdvertLine($advert, 'Hébergement', '60.00', 1);
|
|
$line1->setDescription('Hébergement annuel');
|
|
$line1->setType('hosting');
|
|
$line1->setServiceId(5);
|
|
$advert->addLine($line1);
|
|
|
|
$line2 = new \App\Entity\AdvertLine($advert, 'Domaine', '15.00', 2);
|
|
// no description, no type, no serviceId
|
|
$advert->addLine($line2);
|
|
|
|
$em = $this->createStub(EntityManagerInterface::class);
|
|
$orderService = $this->createStub(OrderNumberService::class);
|
|
|
|
$service = new FactureService($orderService, $em, $this->createStub(\Psr\Log\LoggerInterface::class), self::HMAC_SECRET);
|
|
$facture = $service->createFromAdvert($advert);
|
|
|
|
$this->assertInstanceOf(Facture::class, $facture);
|
|
$this->assertCount(2, $facture->getLines());
|
|
}
|
|
}
|