feat(absences) : fondation backend du module de gestion des absences
Module type Payfit (étapes 1+2 de la spec V1) : demande d'absence, validation admin, soldes à jour. - Enums : AbsenceType, AbsenceStatus, HalfDay, ContractType, FamilySituation - Entités : AbsencePolicy, AbsenceBalance, AbsenceRequest + champs RH sur User - Services : PublicHolidayProvider (fériés FR métropole en PHP pur, Computus), AbsenceDayCalculator (décompte jours ouvrés/ouvrables + demi-journées, TDD), AbsenceBalanceService (périodes + pending/taken/recrédit) - API Platform : providers/processors (création, approve/reject/cancel) + RBAC me/admin, contrôleurs preview (dry-run), upload/download justificatif, calendrier - Migrations : une par table + colonnes RH user (DEFAULT puis DROP DEFAULT) - Fixtures : 5 policies par défaut, salariés démo, soldes et demandes - Tests unitaires : PublicHolidayProvider, AbsenceDayCalculator (12 tests) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
92
tests/Unit/Service/AbsenceDayCalculatorTest.php
Normal file
92
tests/Unit/Service/AbsenceDayCalculatorTest.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Service;
|
||||
|
||||
use App\Enum\HalfDay;
|
||||
use App\Service\AbsenceDayCalculator;
|
||||
use App\Service\PublicHolidayProvider;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class AbsenceDayCalculatorTest extends TestCase
|
||||
{
|
||||
private AbsenceDayCalculator $calculator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->calculator = new AbsenceDayCalculator(new PublicHolidayProvider());
|
||||
}
|
||||
|
||||
public function testFullWeekIsFiveWorkingDays(): void
|
||||
{
|
||||
// Mon 2026-06-01 to Fri 2026-06-05, no holidays that week
|
||||
self::assertSame(5.0, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-06-01'),
|
||||
new DateTimeImmutable('2026-06-05'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testWeekendIsSkipped(): void
|
||||
{
|
||||
// Fri 2026-06-05 to Mon 2026-06-08 => Fri + Mon = 2
|
||||
self::assertSame(2.0, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-06-05'),
|
||||
new DateTimeImmutable('2026-06-08'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testHolidayIsSkipped(): void
|
||||
{
|
||||
// Thu 2026-05-07 to Fri 2026-05-08 (Victoire 1945) => Thu only = 1
|
||||
self::assertSame(1.0, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-05-07'),
|
||||
new DateTimeImmutable('2026-05-08'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testHalfDayStartSubtractsHalf(): void
|
||||
{
|
||||
self::assertSame(4.5, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-06-01'),
|
||||
new DateTimeImmutable('2026-06-05'),
|
||||
HalfDay::Afternoon,
|
||||
));
|
||||
}
|
||||
|
||||
public function testBothHalfDaysSubtractOne(): void
|
||||
{
|
||||
self::assertSame(4.0, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-06-01'),
|
||||
new DateTimeImmutable('2026-06-05'),
|
||||
HalfDay::Afternoon,
|
||||
HalfDay::Morning,
|
||||
));
|
||||
}
|
||||
|
||||
public function testSingleHalfDay(): void
|
||||
{
|
||||
self::assertSame(0.5, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-06-01'),
|
||||
new DateTimeImmutable('2026-06-01'),
|
||||
HalfDay::Morning,
|
||||
));
|
||||
}
|
||||
|
||||
public function testWorkingDaysVsOpenDays(): void
|
||||
{
|
||||
// Fri 2026-06-05 to Mon 2026-06-08, "ouvrables" includes Saturday
|
||||
// => Fri + Sat + Mon = 3 (Sunday always skipped)
|
||||
self::assertSame(3.0, $this->calculator->countWorkingDays(
|
||||
new DateTimeImmutable('2026-06-05'),
|
||||
new DateTimeImmutable('2026-06-08'),
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user