fix: adjust detection of overlapping applications

addresses #869ar02xk
This commit is contained in:
Björn Fromme
2026-08-13 18:47:20 +02:00
parent bdd06f0187
commit 804dab335f
5 changed files with 342 additions and 322 deletions
+62
View File
@@ -8,6 +8,7 @@ use App\Entity\Teamer;
use App\Model\ApplicationFilterDto;
use App\Model\AssignmentFilterDto;
use App\Repository\Traits\QueryHelperTrait;
use Carbon\CarbonPeriod;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\Query;
use Doctrine\Persistence\ManagerRegistry;
@@ -161,6 +162,67 @@ class ApplicationRepository extends ServiceEntityRepository
;
}
/**
* Finds all applications of a teamer whose effective assignment period overlaps the given period.
*
* The effective period of an assignment is its own date range, falling back to the date range of
* its destination whenever the assignment does not override it - the query mirrors
* {@see Assignment::getEffectivePeriod()}. Boundaries count as an overlap: a teamer cannot end one
* assignment on the same day another one begins.
*
* @return array<Application>
*/
public function findOverlappingForTeamer(Teamer $teamer, CarbonPeriod $period): array
{
return $this
->getOverlappingForTeamerQuery($teamer, $period)
->getResult()
;
}
public function getOverlappingForTeamerQuery(Teamer $teamer, CarbonPeriod $period): Query
{
$qb = $this->createQueryBuilder('application');
return $qb
->innerJoin('application.assignment', 'assignment')
->innerJoin('assignment.destination', 'destination')
->where($qb->expr()->andX(
$qb->expr()->eq('application.teamer', ':teamer'),
$qb->expr()->neq('application.status', ':application_rejected'),
$qb->expr()->neq('assignment.status', ':assignment_called_off'),
$qb->expr()->isNull('assignment.deletedAt'),
$qb->expr()->isNull('destination.deletedAt'),
$qb->expr()->orX(
$qb->expr()->andX(
$qb->expr()->isNull('assignment.dateFrom'),
$qb->expr()->lte('destination.dateFrom', ':dateTo')
),
$qb->expr()->andX(
$qb->expr()->isNotNull('assignment.dateFrom'),
$qb->expr()->lte('assignment.dateFrom', ':dateTo')
)
),
$qb->expr()->orX(
$qb->expr()->andX(
$qb->expr()->isNull('assignment.dateTo'),
$qb->expr()->gte('destination.dateTo', ':dateFrom')
),
$qb->expr()->andX(
$qb->expr()->isNotNull('assignment.dateTo'),
$qb->expr()->gte('assignment.dateTo', ':dateFrom')
)
)
))
->setParameter('teamer', $teamer)
->setParameter('application_rejected', Application::STATUS_REJECTED)
->setParameter('assignment_called_off', Assignment::STATUS_CALLED_OFF)
->setParameter('dateFrom', $period->start->toDateTimeImmutable())
->setParameter('dateTo', $period->end->toDateTimeImmutable())
->getQuery()
;
}
public function getCurrentByAssignment(Assignment $assignment): array
{
$qb = $this->createQueryBuilder('application');