feat: all-season assignments
This commit is contained in:
1 parent
675cec1b69
commit
cf876ed224
119 files changed
+6194
-294
No files matched your search
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\SeasonAssignmentTask;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<SeasonAssignmentTask>
|
||||
*
|
||||
* @method SeasonAssignmentTask|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method SeasonAssignmentTask|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method SeasonAssignmentTask[] findAll()
|
||||
* @method SeasonAssignmentTask[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class SeasonAssignmentTaskRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, SeasonAssignmentTask::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Every open entry that could still be reminded about: not ticked off, on a live assignment
|
||||
* that has a teamer on it.
|
||||
*
|
||||
* The deadlines themselves are not part of this query. They are computed from the
|
||||
* assignment's first day by a relative offset, and month arithmetic is not invertible
|
||||
* day by day - "minus one month" from the 31st and back again lands somewhere else - so a
|
||||
* query built by inverting the offset would silently skip entries. The reminder resolves
|
||||
* every row through SeasonTaskDeadlineResolver instead; the set is small, one assignment per
|
||||
* all-season teamer per season.
|
||||
*
|
||||
* @return SeasonAssignmentTask[]
|
||||
*/
|
||||
public function findOpen(?\DateTimeImmutable $windowStart = null, ?\DateTimeImmutable $windowEnd = null): array
|
||||
{
|
||||
return $this
|
||||
->createOpenQueryBuilder($windowStart, $windowEnd)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracted so the conditions can be pinned by a test compiling the DQL - the suite has no
|
||||
* fixtures, so what is asserted is what the query says, not what it returns.
|
||||
*/
|
||||
public function createOpenQueryBuilder(
|
||||
?\DateTimeImmutable $windowStart = null,
|
||||
?\DateTimeImmutable $windowEnd = null,
|
||||
): QueryBuilder {
|
||||
$qb = $this->createQueryBuilder('task');
|
||||
|
||||
$qb
|
||||
->select('task', 'season_assignment', 'teamer')
|
||||
->innerJoin('task.seasonAssignment', 'season_assignment')
|
||||
// no teamer means nobody to remind and nobody to be late
|
||||
->innerJoin('season_assignment.teamer', 'teamer')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->eq('task.done', ':done'),
|
||||
$qb->expr()->isNull('season_assignment.deletedAt'),
|
||||
$qb->expr()->isNull('teamer.deletedAt')
|
||||
))
|
||||
->setParameter('done', false)
|
||||
->addOrderBy('teamer.lastName', \SortDirection::Ascending)
|
||||
->addOrderBy('teamer.firstName', \SortDirection::Ascending)
|
||||
;
|
||||
|
||||
if (null !== $windowStart) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->gte('season_assignment.dateFrom', ':windowStart'))
|
||||
->setParameter('windowStart', $windowStart)
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $windowEnd) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->lte('season_assignment.dateFrom', ':windowEnd'))
|
||||
->setParameter('windowEnd', $windowEnd)
|
||||
;
|
||||
}
|
||||
|
||||
return $qb;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user