feat: remove obsolete date range override
This commit is contained in:
@@ -36,7 +36,7 @@ class IndexController extends AbstractController
|
||||
$request->query->getInt('page', 1),
|
||||
$request->query->getInt('limit', 50),
|
||||
[
|
||||
'defaultSortFieldName' => 'assignment.dateFrom',
|
||||
'defaultSortFieldName' => 'destination.dateFrom',
|
||||
'defaultSortDirection' => 'asc',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -37,7 +37,7 @@ class IndexController extends AbstractController
|
||||
$request->query->getInt('page', 1),
|
||||
9,
|
||||
[
|
||||
'defaultSortFieldName' => 'assignment.dateFrom',
|
||||
'defaultSortFieldName' => 'destination.dateFrom',
|
||||
'defaultSortDirection' => 'asc',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -37,7 +37,7 @@ class IndexController extends AbstractController
|
||||
$request->query->getInt('page', 1),
|
||||
9,
|
||||
[
|
||||
'defaultSortFieldName' => 'assignment.dateFrom',
|
||||
'defaultSortFieldName' => 'destination.dateFrom',
|
||||
'defaultSortDirection' => 'asc',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -35,8 +35,8 @@ class IcsController extends AbstractController
|
||||
$filename = sprintf(
|
||||
'Einteilung_%s_%s-%s.ics',
|
||||
$jobProfile->getName(),
|
||||
$assignment->getEffectivePeriod()->start->format('d.m.Y'),
|
||||
$assignment->getEffectivePeriod()->end->format('d.m.Y')
|
||||
$destination->getDateFrom()->format('d.m.Y'),
|
||||
$destination->getDateTo()->format('d.m.Y')
|
||||
);
|
||||
$slugger = new AsciiSlugger();
|
||||
$filename = $slugger->slug($filename);
|
||||
|
||||
@@ -37,7 +37,7 @@ class RecentController extends AbstractController
|
||||
$request->query->getInt('page', 1),
|
||||
9,
|
||||
[
|
||||
'defaultSortFieldName' => 'assignment.dateFrom',
|
||||
'defaultSortFieldName' => 'destination.dateFrom',
|
||||
'defaultSortDirection' => 'asc',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -37,7 +37,7 @@ class UpcomingController extends AbstractController
|
||||
$request->query->getInt('page', 1),
|
||||
9,
|
||||
[
|
||||
'defaultSortFieldName' => 'assignment.dateFrom',
|
||||
'defaultSortFieldName' => 'destination.dateFrom',
|
||||
'defaultSortDirection' => 'asc',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Entity\Traits\BlameableEntity;
|
||||
use App\Entity\Traits\SoftDeletableEntity;
|
||||
use App\Entity\Traits\TimestampableEntity;
|
||||
use App\Repository\AssignmentRepository;
|
||||
use Carbon\CarbonPeriodImmutable;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
@@ -64,13 +63,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
#[ORM\Column]
|
||||
private bool $skipFormalities = false;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||
private ?\DateTimeImmutable $dateFrom = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||
#[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Enddatum muss nach dem Beginndatum liegen')]
|
||||
private ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||
private ?\DateTimeImmutable $pickupDate = null;
|
||||
|
||||
@@ -133,8 +125,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
->setAvailableDispositions($assignment->getAvailableDispositions())
|
||||
->setShowAvailableDispositions($assignment->isShowAvailableDispositions())
|
||||
->setSkipFormalities($assignment->isSkipFormalities())
|
||||
->setDateFrom($assignment->getDateFrom())
|
||||
->setDateTo($assignment->getDateTo())
|
||||
->setPickupDate($assignment->getPickupDate())
|
||||
->setPickup($assignment->getPickup())
|
||||
->setBenefits($assignment->getBenefits())
|
||||
@@ -266,66 +256,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateFrom(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->dateFrom;
|
||||
}
|
||||
|
||||
public function setDateFrom(?\DateTimeImmutable $dateFrom): static
|
||||
{
|
||||
$this->dateFrom = $dateFrom;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateTo(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->dateTo;
|
||||
}
|
||||
|
||||
public function setDateTo(?\DateTimeImmutable $dateTo): static
|
||||
{
|
||||
$this->dateTo = $dateTo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Immutable on purpose: a plain CarbonPeriod hands out mutable Carbon instances, so a caller
|
||||
* deriving one date from another - `$end = $period->getEndDate(); $end->addDays(14)` - moves
|
||||
* the original as well and silently collapses its own period. CarbonPeriodImmutable yields
|
||||
* CarbonImmutable from start, end and getEndDate(), which makes that mistake impossible.
|
||||
*/
|
||||
public function getEffectivePeriod(): ?CarbonPeriodImmutable
|
||||
{
|
||||
if (null !== $destination = $this->getDestination()) {
|
||||
$dateFrom = $this->getDateFrom() ?? $destination->getDateFrom();
|
||||
$dateTo = $this->getDateTo() ?? $destination->getDateTo();
|
||||
|
||||
return new CarbonPeriodImmutable($dateFrom, $dateTo);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getEffectiveDateFrom(): ?\DateTimeImmutable
|
||||
{
|
||||
if (null !== $effectivePeriod = $this->getEffectivePeriod()) {
|
||||
return $effectivePeriod->start->toDateTimeImmutable();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getEffectiveDateTo(): ?\DateTimeImmutable
|
||||
{
|
||||
if (null !== $effectivePeriod = $this->getEffectivePeriod()) {
|
||||
return $effectivePeriod->end->toDateTimeImmutable();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getEffectivePickupDate(): ?\DateTimeImmutable
|
||||
{
|
||||
if (null !== $this->pickupDate) {
|
||||
|
||||
@@ -246,9 +246,8 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
||||
}
|
||||
|
||||
$assignment = $this->getAssignment();
|
||||
$assignmentPeriod = $assignment->getEffectivePeriod();
|
||||
$dueDateFrom = $this->getCreatedAt()->modify(sprintf('+%d days', $deadlineDays));
|
||||
$dueDateTo = $assignmentPeriod->end->modify('-1 day');
|
||||
$dueDateTo = $assignment->getDestination()->getDateTo()->modify('-1 day');
|
||||
|
||||
// A short-notice assignment can end before the normal $deadlineDays window would even
|
||||
// start. Left uncapped, dueDateFrom >= dueDateTo makes isStarted() and isEnded() equal
|
||||
@@ -297,9 +296,8 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
||||
}
|
||||
|
||||
$assignment = $this->getAssignment();
|
||||
$assignmentPeriod = $assignment->getEffectivePeriod();
|
||||
$dueDateFrom = $assignmentPeriod->getEndDate();
|
||||
$dueDateTo = $dueDateFrom->addDays($deadlineDays);
|
||||
$dueDateFrom = $assignment->getDestination()->getDateTo();
|
||||
$dueDateTo = $dueDateFrom->modify(sprintf('+%d days', $deadlineDays));
|
||||
|
||||
$period = CarbonPeriodImmutable::create($dueDateFrom, $dueDateTo);
|
||||
|
||||
|
||||
@@ -98,8 +98,8 @@ class Feedback implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
|
||||
$instance
|
||||
->setAssignment($assignment)
|
||||
->setAssignmentDateFrom($assignment->getEffectiveDateFrom())
|
||||
->setAssignmentDateTo($assignment->getEffectiveDateTo())
|
||||
->setAssignmentDateFrom($destination->getDateFrom())
|
||||
->setAssignmentDateTo($destination->getDateTo())
|
||||
->setDestinationName($destination->getProduct())
|
||||
->setHotel($destination->getHotel())
|
||||
->setHotelCode($destination->getHotelCode())
|
||||
|
||||
@@ -75,14 +75,13 @@ class DispositionWorkflowGuardSubscriber implements EventSubscriberInterface
|
||||
/** @var Disposition $disposition */
|
||||
$disposition = $event->getSubject();
|
||||
$assignment = $disposition->getAssignment();
|
||||
$assignmentPeriod = $assignment->getEffectivePeriod();
|
||||
$today = new \DateTimeImmutable();
|
||||
|
||||
$dueDateFrom = $disposition
|
||||
->getCreatedAt()
|
||||
->modify(sprintf('+%d days', $this->contractUploadDeadlineDays))
|
||||
;
|
||||
$dueDateTo = $assignmentPeriod->end->modify('-1 day');
|
||||
$dueDateTo = $assignment->getDestination()->getDateTo()->modify('-1 day');
|
||||
|
||||
// Block upload if deadline has passed
|
||||
if ($dueDateTo < $today) {
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Entity\Upload;
|
||||
use App\Event\ApplicationDeletedEvent;
|
||||
use App\Event\DocumentConfirmedEvent;
|
||||
use App\Repository\ApplicationRepository;
|
||||
use Carbon\CarbonPeriodImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
|
||||
@@ -37,10 +38,12 @@ class InvalidateApplicationsListener
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $period = $disposition->getAssignment()->getEffectivePeriod()) {
|
||||
if (null === $destination = $disposition->getAssignment()->getDestination()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$period = new CarbonPeriodImmutable($destination->getDateFrom(), $destination->getDateTo());
|
||||
|
||||
$applications = $this->applicationRepository->findOverlappingForTeamer($teamer, $period);
|
||||
|
||||
if (0 === count($applications)) {
|
||||
@@ -55,8 +58,8 @@ class InvalidateApplicationsListener
|
||||
'teamer' => $teamer->getUuid(),
|
||||
'teamer_name' => (string) $teamer,
|
||||
'destination' => $assignment->getDestination()->getHotelCode(),
|
||||
'date_from' => $assignment->getEffectiveDateFrom()->format('Y-m-d'),
|
||||
'date_to' => $assignment->getEffectiveDateTo()->format('Y-m-d'),
|
||||
'date_from' => $assignment->getDestination()->getDateFrom()->format('Y-m-d'),
|
||||
'date_to' => $assignment->getDestination()->getDateTo()->format('Y-m-d'),
|
||||
]);
|
||||
$this->entityManager->remove($application);
|
||||
}
|
||||
|
||||
@@ -79,14 +79,6 @@ class AssignmentType extends AbstractType
|
||||
'rows' => 3,
|
||||
],
|
||||
])
|
||||
// ->add('dateFrom', DatepickerType::class, [
|
||||
// 'label' => 'abweichender Einsatztermin von',
|
||||
// 'required' => false,
|
||||
// ])
|
||||
// ->add('dateTo', DatepickerType::class, [
|
||||
// 'label' => 'abweichender Einsatztermin bis',
|
||||
// 'required' => false,
|
||||
// ])
|
||||
// ->add('pickupDate', DatepickerType::class, [
|
||||
// 'label' => 'abweichender Zustieg bei Busbegleitung',
|
||||
// 'required' => false,
|
||||
|
||||
@@ -163,12 +163,10 @@ class ApplicationRepository extends ServiceEntityRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all applications of a teamer whose effective assignment period overlaps the given period.
|
||||
* Finds all applications of a teamer whose 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.
|
||||
* The assignment period is the date range of its destination. Boundaries count as an
|
||||
* overlap: a teamer cannot end one assignment on the same day another one begins.
|
||||
*
|
||||
* @return array<Application>
|
||||
*/
|
||||
@@ -193,26 +191,8 @@ class ApplicationRepository extends ServiceEntityRepository
|
||||
$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')
|
||||
)
|
||||
)
|
||||
$qb->expr()->lte('destination.dateFrom', ':dateTo'),
|
||||
$qb->expr()->gte('destination.dateTo', ':dateFrom')
|
||||
))
|
||||
->setParameter('teamer', $teamer)
|
||||
->setParameter('application_rejected', Application::STATUS_REJECTED)
|
||||
|
||||
@@ -73,13 +73,7 @@ class AssignmentRepository extends ServiceEntityRepository
|
||||
->innerJoin('assignment.destination', 'destination')
|
||||
->innerJoin('assignment.jobProfile', 'job_profile')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('destination.dateFrom', ':now'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateFrom'),
|
||||
$qb->expr()->gt('assignment.dateFrom', ':now')
|
||||
)
|
||||
),
|
||||
$qb->expr()->gt('destination.dateFrom', ':now'),
|
||||
$qb->expr()->isNull('assignment.deletedAt'),
|
||||
$qb->expr()->notIn('assignment.status', ':status'),
|
||||
$qb->expr()->in('assignment.id', $availableAssignmentsIds)
|
||||
@@ -399,13 +393,7 @@ class AssignmentRepository extends ServiceEntityRepository
|
||||
)
|
||||
->innerJoin('assignment.destination', 'destination')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('destination.dateFrom', ':now'),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateFrom'),
|
||||
$qb->expr()->gt('assignment.dateFrom', ':now')
|
||||
)
|
||||
),
|
||||
$qb->expr()->gt('destination.dateFrom', ':now'),
|
||||
$qb->expr()->notIn('assignment.status', ':status'),
|
||||
$qb->expr()->isNull('assignment.deletedAt')
|
||||
))
|
||||
|
||||
@@ -11,7 +11,6 @@ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\Query\Expr\Comparison;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\Query\Expr\Orx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
@@ -43,16 +42,7 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
$qb->expr()->eq('disposition.teamer', ':teamer'),
|
||||
$qb->expr()->neq('assignment.status', ':assignmentStatus'),
|
||||
$qb->expr()->neq('disposition.status', ':dispositionStatus'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull('assignment.dateTo'),
|
||||
$qb->expr()->gte('destination.dateTo', ':date')
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->gte('assignment.dateTo', ':date')
|
||||
)
|
||||
)
|
||||
$qb->expr()->gte('destination.dateTo', ':date')
|
||||
))
|
||||
->setParameter('teamer', $teamer)
|
||||
->setParameter('assignmentStatus', Assignment::STATUS_CALLED_OFF)
|
||||
@@ -85,16 +75,7 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
$qb->expr()->eq('disposition.teamer', ':teamer'),
|
||||
$qb->expr()->neq('assignment.status', ':assignmentStatus'),
|
||||
$qb->expr()->neq('disposition.status', ':dispositionStatus'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull('assignment.dateTo'),
|
||||
$qb->expr()->lte('destination.dateTo', ':date')
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->lte('assignment.dateTo', ':date')
|
||||
)
|
||||
)
|
||||
$qb->expr()->lte('destination.dateTo', ':date')
|
||||
))
|
||||
->setParameter('teamer', $teamer)
|
||||
->setParameter('assignmentStatus', Assignment::STATUS_CALLED_OFF)
|
||||
@@ -145,12 +126,12 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* The effective start date of every non-called-off disposition of a teamer, one row
|
||||
* each, for the per-season tally in the info modal.
|
||||
* The start date of every non-called-off disposition of a teamer, one row each, for the
|
||||
* per-season tally in the info modal.
|
||||
*
|
||||
* Same teamer/called-off filtering as findRecentDispositionsByTeamer(), but unbounded
|
||||
* and stripped to the one date it needs: assignment.dateFrom falling back to the
|
||||
* destination's, the season convention shared with SeasonPeriodFilter.
|
||||
* and stripped to the one date it needs: the destination's start, the season convention
|
||||
* shared with SeasonPeriodFilter.
|
||||
*
|
||||
* @return array<int, array{seasonDate: string}>
|
||||
*/
|
||||
@@ -159,7 +140,7 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
$qb = $this->createQueryBuilder('disposition');
|
||||
|
||||
return $qb
|
||||
->select('COALESCE(assignment.dateFrom, destination.dateFrom) AS seasonDate')
|
||||
->select('destination.dateFrom AS seasonDate')
|
||||
->innerJoin('disposition.assignment', 'assignment')
|
||||
->innerJoin('assignment.destination', 'destination')
|
||||
->where($qb->expr()->andX(
|
||||
@@ -242,13 +223,7 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
->leftJoin('disposition.feedback', 'feedback')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->notIn('assignment.status', ':status'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->lte('assignment.dateTo', ':dateTo')
|
||||
),
|
||||
$qb->expr()->lte('destination.dateTo', ':dateTo')
|
||||
),
|
||||
$qb->expr()->lte('destination.dateTo', ':dateTo'),
|
||||
$qb->expr()->isNull('feedback'),
|
||||
$this->excludesSkipFormalities($qb)
|
||||
))
|
||||
@@ -302,13 +277,7 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
->innerJoin('assignment.destination', 'destination')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->in('disposition.status', ':status'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->lte('assignment.dateTo', ':dateTo')
|
||||
),
|
||||
$qb->expr()->lte('destination.dateTo', ':dateTo')
|
||||
)
|
||||
$qb->expr()->lte('destination.dateTo', ':dateTo')
|
||||
))
|
||||
->setParameter('status', [
|
||||
Disposition::STATUS_NEW,
|
||||
@@ -529,10 +498,10 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
$normalDay = $qb->expr()->andX(
|
||||
$qb->expr()->gte('disposition.createdAt', ':dayStart'),
|
||||
$qb->expr()->lt('disposition.createdAt', ':dayEnd'),
|
||||
$this->effectiveDateToGreaterThan($qb, ':tomorrow'),
|
||||
$qb->expr()->gt('destination.dateTo', ':tomorrow'),
|
||||
);
|
||||
$shortNoticeDay = $qb->expr()->andX(
|
||||
$this->effectiveDateToEquals($qb, ':tomorrow'),
|
||||
$qb->expr()->eq('destination.dateTo', ':tomorrow'),
|
||||
$qb->expr()->gte('disposition.createdAt', ':dayStart'),
|
||||
);
|
||||
|
||||
@@ -599,7 +568,7 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
// in CronCommand, so a skip-formalities placement is still `confirmed` here and
|
||||
// would slip past the status filter on the day after the assignment ends.
|
||||
$this->excludesSkipFormalities($qb),
|
||||
$this->effectiveDateToEquals($qb, ':endDate'),
|
||||
$qb->expr()->eq('destination.dateTo', ':endDate'),
|
||||
))
|
||||
->setParameter('documentType', Upload::TYPE_INVOICE)
|
||||
->setParameter('dispositionStatus', [Disposition::STATUS_CALLED_OFF, Disposition::STATUS_COMPLETED])
|
||||
@@ -611,30 +580,6 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the assignment's end date against $parameter, falling back to the destination's
|
||||
* when the assignment does not override it.
|
||||
*
|
||||
* The fallback is guarded on both sides - without the isNull() on the second branch an
|
||||
* assignment that moves the end date into the future would still match on the
|
||||
* destination's date. Kept in one place because the per-assignment date override is due to
|
||||
* be removed (docs/remove-assignment-date-override.md), and this then collapses to a plain
|
||||
* comparison on destination.dateTo.
|
||||
*/
|
||||
private function effectiveDateToEquals(QueryBuilder $qb, string $parameter): Orx
|
||||
{
|
||||
return $qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->eq('assignment.dateTo', $parameter)
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull('assignment.dateTo'),
|
||||
$qb->expr()->eq('destination.dateTo', $parameter)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts a query to assignments that still run the contract, invoice and feedback process.
|
||||
*
|
||||
@@ -653,23 +598,6 @@ class DispositionRepository extends ServiceEntityRepository
|
||||
return $qb->expr()->eq('assignment.skipFormalities', ':skipFormalities');
|
||||
}
|
||||
|
||||
/**
|
||||
* Same fallback as effectiveDateToEquals(), but for "later than $parameter".
|
||||
*/
|
||||
private function effectiveDateToGreaterThan(QueryBuilder $qb, string $parameter): Orx
|
||||
{
|
||||
return $qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->gt('assignment.dateTo', $parameter)
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull('assignment.dateTo'),
|
||||
$qb->expr()->gt('destination.dateTo', $parameter)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispositions whose contract upload period has run out, for the admin dashboard.
|
||||
*
|
||||
|
||||
@@ -5,15 +5,14 @@ namespace App\Repository\Filter;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
/**
|
||||
* Narrows a query to the season an assignment runs in.
|
||||
* Narrows a query to the season an assignment runs in, which is the date range of its
|
||||
* destination.
|
||||
*
|
||||
* The season is assignment.dateFrom/dateTo falling back to the destination's, mirroring
|
||||
* Assignment::getEffectivePeriod(), which DQL cannot call. Every statistics screen means
|
||||
* this by a date range, so it lives in one place: three repositories carrying the same
|
||||
* expression by hand is three chances for "a season" to come to mean something slightly
|
||||
* different on one screen than on the one beside it.
|
||||
* Kept in one place because every statistics screen means the same thing by "a season":
|
||||
* the expression carried by hand in each repository is one more chance for it to come to
|
||||
* mean something slightly different on one screen than on the one beside it.
|
||||
*
|
||||
* Both aliases must already be joined by the caller - this only adds the conditions.
|
||||
* The destination alias must already be joined by the caller - this only adds the conditions.
|
||||
*/
|
||||
final class SeasonPeriodFilter
|
||||
{
|
||||
@@ -21,37 +20,18 @@ final class SeasonPeriodFilter
|
||||
QueryBuilder $qb,
|
||||
?\DateTimeImmutable $dateFrom,
|
||||
?\DateTimeImmutable $dateTo,
|
||||
string $assignmentAlias = 'assignment',
|
||||
string $destinationAlias = 'destination',
|
||||
): void {
|
||||
if (null !== $dateFrom) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull($assignmentAlias.'.dateFrom'),
|
||||
$qb->expr()->gte($assignmentAlias.'.dateFrom', ':dateFrom')
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull($assignmentAlias.'.dateFrom'),
|
||||
$qb->expr()->gte($destinationAlias.'.dateFrom', ':dateFrom')
|
||||
)
|
||||
))
|
||||
->andWhere($qb->expr()->gte($destinationAlias.'.dateFrom', ':dateFrom'))
|
||||
->setParameter('dateFrom', $dateFrom)
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $dateTo) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull($assignmentAlias.'.dateTo'),
|
||||
$qb->expr()->lte($assignmentAlias.'.dateTo', ':dateTo')
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull($assignmentAlias.'.dateTo'),
|
||||
$qb->expr()->lte($destinationAlias.'.dateTo', ':dateTo')
|
||||
)
|
||||
))
|
||||
->andWhere($qb->expr()->lte($destinationAlias.'.dateTo', ':dateTo'))
|
||||
->setParameter('dateTo', $dateTo)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@ class IcsGenerator
|
||||
$label = sprintf('E&P: Einteilung als %s', $assignment->getJobProfile()->getName());
|
||||
$address = sprintf("%s\n%s", $assignment->getDestination()->getProduct(), $assignment->getDestination()->getHotel());
|
||||
|
||||
$destination = $assignment->getDestination();
|
||||
|
||||
$event = Event::create($label)
|
||||
->startsAt($assignment->getEffectivePeriod()->start)
|
||||
->endsAt($assignment->getEffectivePeriod()->end->modify('+1 day'))
|
||||
->startsAt($destination->getDateFrom())
|
||||
->endsAt($destination->getDateTo()->modify('+1 day'))
|
||||
->address($address)
|
||||
->description($label)
|
||||
;
|
||||
|
||||
@@ -39,8 +39,8 @@ class ContractRenderer extends AbstractPdfRenderer
|
||||
$pdf->Text(21, 104.5, $pdf->encodeString($assignment->getJobProfile()->getName()));
|
||||
|
||||
// Period
|
||||
$dateFrom = $assignment->getEffectivePeriod()->start->format('d.m.Y');
|
||||
$dateTo = $assignment->getEffectivePeriod()->end->format('d.m.Y');
|
||||
$dateFrom = $destination->getDateFrom()->format('d.m.Y');
|
||||
$dateTo = $destination->getDateTo()->format('d.m.Y');
|
||||
$period = sprintf('%s - %s', $dateFrom, $dateTo);
|
||||
$pdf->Text(57, 113, $period);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class InvoiceRenderer extends AbstractPdfRenderer
|
||||
|
||||
// Invoice number
|
||||
$pdf->SetFont('Arial', '', 12);
|
||||
$date = $assignment->getEffectivePeriod()->start->format('d/m/Y');
|
||||
$date = $assignment->getDestination()->getDateFrom()->format('d/m/Y');
|
||||
$suffix = $assignment->getId();
|
||||
$number = sprintf('%s-%05d', $date, $suffix);
|
||||
$pdf->Text(85, 116, $number);
|
||||
|
||||
@@ -37,12 +37,12 @@ class ApplicationValidator extends ConstraintValidator
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $period = $application->getAssignment()->getEffectivePeriod()) {
|
||||
if (null === $destination = $application->getAssignment()->getDestination()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$applicationDateFrom = $period->start->toDateTimeImmutable();
|
||||
$applicationDateTo = $period->end->toDateTimeImmutable();
|
||||
$applicationDateFrom = $destination->getDateFrom();
|
||||
$applicationDateTo = $destination->getDateTo();
|
||||
|
||||
$qb = $this
|
||||
->dispositionRepository
|
||||
@@ -62,26 +62,8 @@ class ApplicationValidator extends ConstraintValidator
|
||||
$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', ':application_date_to')
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateFrom'),
|
||||
$qb->expr()->lte('assignment.dateFrom', ':application_date_to')
|
||||
)
|
||||
),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNull('assignment.dateTo'),
|
||||
$qb->expr()->gte('destination.dateTo', ':application_date_from')
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->isNotNull('assignment.dateTo'),
|
||||
$qb->expr()->gte('assignment.dateTo', ':application_date_from')
|
||||
)
|
||||
)
|
||||
$qb->expr()->lte('destination.dateFrom', ':application_date_to'),
|
||||
$qb->expr()->gte('destination.dateTo', ':application_date_from')
|
||||
))
|
||||
->setParameter('teamer', $teamer)
|
||||
->setParameter('disposition_called_off', Disposition::STATUS_CALLED_OFF)
|
||||
|
||||
Reference in New Issue
Block a user