feat: remove obsolete date range override

This commit is contained in:
2026-08-31 16:56:36 +02:00
parent 86c5d23181
commit 127ced4378
42 changed files with 152 additions and 353 deletions
@@ -95,7 +95,7 @@ class InvalidateApplicationsListenerTest extends TestCase
$this->assertSame([], $this->removedApplications);
}
public function testIgnoresAssignmentsWithoutEffectivePeriod(): void
public function testIgnoresAssignmentsWithoutDestination(): void
{
$document = $this->createContract(null, $this->createTeamer());
@@ -125,7 +125,7 @@ class InvalidateApplicationsListenerTest extends TestCase
$this->assertSame([], $this->dispatchedEvents);
}
public function testQueriesOverlappingApplicationsForTheTeamerAndTheEffectivePeriod(): void
public function testQueriesOverlappingApplicationsForTheTeamerAndTheDestinationPeriod(): void
{
$teamer = $this->createTeamer();
$period = new CarbonPeriodImmutable('2025-01-10', '2025-01-20');
@@ -134,7 +134,13 @@ class InvalidateApplicationsListenerTest extends TestCase
$this->applicationRepository
->expects($this->once())
->method('findOverlappingForTeamer')
->with($teamer, $period)
->with(
$this->identicalTo($teamer),
$this->callback(static function (CarbonPeriodImmutable $actual) use ($period): bool {
return $actual->getStartDate()->equalTo($period->getStartDate())
&& $actual->getEndDate()->equalTo($period->getEndDate());
})
)
->willReturn([])
;
@@ -194,7 +200,15 @@ class InvalidateApplicationsListenerTest extends TestCase
private function createContract(?CarbonPeriodImmutable $period, Teamer $teamer): Upload&MockObject
{
$assignment = $this->createMock(Assignment::class);
$assignment->method('getEffectivePeriod')->willReturn($period);
if (null === $period) {
$assignment->method('getDestination')->willReturn(null);
} else {
$destination = $this->createMock(Destination::class);
$destination->method('getDateFrom')->willReturn($period->getStartDate()->toDateTimeImmutable());
$destination->method('getDateTo')->willReturn($period->getEndDate()->toDateTimeImmutable());
$assignment->method('getDestination')->willReturn($destination);
}
$disposition = $this->createMock(Disposition::class);
$disposition->method('getAssignment')->willReturn($assignment);
@@ -211,12 +225,12 @@ class InvalidateApplicationsListenerTest extends TestCase
{
$destination = $this->createMock(Destination::class);
$destination->method('getHotelCode')->willReturn('TST');
$destination->method('getDateFrom')->willReturn(new \DateTimeImmutable('2025-01-12'));
$destination->method('getDateTo')->willReturn(new \DateTimeImmutable('2025-01-18'));
$assignment = $this->createMock(Assignment::class);
$assignment->method('getDestination')->willReturn($destination);
$assignment->method('getUuid')->willReturn('assignment-uuid');
$assignment->method('getEffectiveDateFrom')->willReturn(new \DateTimeImmutable('2025-01-12'));
$assignment->method('getEffectiveDateTo')->willReturn(new \DateTimeImmutable('2025-01-18'));
$application = $this->createMock(Application::class);
$application->method('getUuid')->willReturn('application-uuid');
+4 -12
View File
@@ -20,21 +20,13 @@ use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
*/
class ApplicationRepositoryTest extends KernelTestCase
{
public function testOverlappingQueryUsesInclusiveBoundariesAndEffectiveDates(): void
public function testOverlappingQueryUsesInclusiveBoundariesOnTheDestinationDates(): void
{
$dql = $this->createOverlappingQuery()->getDQL();
// an assignment overrides the date range of its destination, so both have to be considered
$this->assertStringContainsString(
'(assignment.dateFrom IS NULL AND destination.dateFrom <= :dateTo)'
.' OR (assignment.dateFrom IS NOT NULL AND assignment.dateFrom <= :dateTo)',
$dql
);
$this->assertStringContainsString(
'(assignment.dateTo IS NULL AND destination.dateTo >= :dateFrom)'
.' OR (assignment.dateTo IS NOT NULL AND assignment.dateTo >= :dateFrom)',
$dql
);
// the assignment period is the date range of its destination
$this->assertStringContainsString('destination.dateFrom <= :dateTo', $dql);
$this->assertStringContainsString('destination.dateTo >= :dateFrom', $dql);
// strict comparisons would let assignments that touch on a boundary pass and could never
// match a single day assignment at all
+7 -21
View File
@@ -93,14 +93,8 @@ class DispositionRepositoryTest extends KernelTestCase
{
$dql = $this->contractQuery()->getDQL();
$this->assertStringContainsString(
'assignment.dateTo IS NOT NULL AND assignment.dateTo > :tomorrow',
$dql
);
$this->assertStringContainsString(
'assignment.dateTo IS NOT NULL AND assignment.dateTo = :tomorrow',
$dql
);
$this->assertStringContainsString('destination.dateTo > :tomorrow', $dql);
$this->assertStringContainsString('destination.dateTo = :tomorrow', $dql);
}
public function testContractReminderBindsTomorrowAsADateAndNotATimestamp(): void
@@ -114,8 +108,8 @@ class DispositionRepositoryTest extends KernelTestCase
}
/**
* The bug that killed this query: destination.dateTo and assignment.dateTo are DATE columns,
* and Doctrine binds a DateTimeImmutable as 'Y-m-d H:i:s', which a DATE never equals.
* The bug that killed this query: destination.dateTo is a DATE column, and Doctrine binds a
* DateTimeImmutable as 'Y-m-d H:i:s', which a DATE never equals.
*/
public function testInvoiceReminderBindsADateAndNotATimestamp(): void
{
@@ -129,21 +123,13 @@ class DispositionRepositoryTest extends KernelTestCase
}
/**
* Without the IS NULL guard on the second branch, an assignment that moves the end date into
* the future still matches on its destination's date.
* The reminder fires for placements whose destination ends on exactly $endDate.
*/
public function testInvoiceReminderGuardsTheDestinationFallback(): void
public function testInvoiceReminderComparesTheDestinationEndDate(): void
{
$dql = $this->invoiceQuery()->getDQL();
$this->assertStringContainsString(
'assignment.dateTo IS NOT NULL AND assignment.dateTo = :endDate',
$dql
);
$this->assertStringContainsString(
'assignment.dateTo IS NULL AND destination.dateTo = :endDate',
$dql
);
$this->assertStringContainsString('destination.dateTo = :endDate', $dql);
}
public function testInvoiceReminderOnlyJoinsTheInvoiceAndSkipsFinishedDispositions(): void
@@ -24,25 +24,21 @@ class StatisticsEventRepositoryTest extends KernelTestCase
{
$dql = $this->query(dateFrom: new \DateTimeImmutable('2026-07-01'))->getDQL();
$this->assertStringContainsString('assignment.dateFrom >= :dateFrom', $dql);
$this->assertStringContainsString('destination.dateFrom >= :dateFrom', $dql);
$this->assertStringNotContainsString('event.occurredAt', $dql);
}
/**
* The season start is assignment.dateFrom falling back to the destination's, per
* Assignment::getEffectivePeriod(). Losing the fallback would silently drop every
* assignment that inherits its dates.
* The season is the destination's date range, the convention shared with SeasonPeriodFilter.
*/
public function testTheSeasonFallsBackToTheDestinationDates(): void
public function testTheSeasonIsTheDestinationDateRange(): void
{
$dql = $this->query(
dateFrom: new \DateTimeImmutable('2026-07-01'),
dateTo: new \DateTimeImmutable('2027-06-30'),
)->getDQL();
$this->assertStringContainsString('assignment.dateFrom IS NULL', $dql);
$this->assertStringContainsString('destination.dateFrom >= :dateFrom', $dql);
$this->assertStringContainsString('assignment.dateTo IS NULL', $dql);
$this->assertStringContainsString('destination.dateTo <= :dateTo', $dql);
}
@@ -17,7 +17,6 @@ use App\Service\Pdf\InvoiceApprover;
use App\Service\Pdf\InvoiceRenderer;
use App\Service\Pdf\Pdf;
use App\Service\Upload\UploadHandler;
use Carbon\CarbonPeriodImmutable;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Contracts\Translation\TranslatorInterface;
@@ -84,7 +83,6 @@ class InvoiceRendererTest extends WebTestCase
;
$assignment = $this->createMock(Assignment::class);
$assignment->method('getEffectivePeriod')->willReturn(CarbonPeriodImmutable::create('2025-02-01', '2025-02-08'));
$assignment->method('getId')->willReturn(1234);
$assignment->method('getDestination')->willReturn($destination);
$assignment->method('getJobProfile')->willReturn($jobProfile);