127 lines
3.8 KiB
PHP
127 lines
3.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Repository;
|
|
|
|
use App\Entity\BookingEditDraft;
|
|
use App\Entity\User;
|
|
use App\Form\Model\Filter\BookingEditDraftFilterDto;
|
|
use App\Repository\Filter\AppliesListFiltersTrait;
|
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
use Doctrine\ORM\Query\Expr\Join;
|
|
use Doctrine\ORM\Query\Parameter;
|
|
use Doctrine\ORM\QueryBuilder;
|
|
use Doctrine\Persistence\ManagerRegistry;
|
|
|
|
/**
|
|
* @extends ServiceEntityRepository<BookingEditDraft>
|
|
*/
|
|
class BookingEditDraftRepository extends ServiceEntityRepository
|
|
{
|
|
use AppliesListFiltersTrait;
|
|
|
|
public function __construct(ManagerRegistry $registry)
|
|
{
|
|
parent::__construct($registry, BookingEditDraft::class);
|
|
}
|
|
|
|
public function createFilteredQueryBuilder(BookingEditDraftFilterDto $filter): QueryBuilder
|
|
{
|
|
$qb = $this
|
|
->createQueryBuilder('booking_edit_draft')
|
|
->leftJoin('booking_edit_draft.user', 'user')
|
|
;
|
|
|
|
$this->applySearchTerm($qb, $filter->searchTerm(), [
|
|
'user.email',
|
|
'booking_edit_draft.bookingNumber',
|
|
'booking_edit_draft.bookingId',
|
|
]);
|
|
|
|
$this->applyDateWithin($qb, 'booking_edit_draft.createdAt', $filter->dateFrom, $filter->dateTo);
|
|
|
|
if (null !== $filter->user) {
|
|
$qb->andWhere('booking_edit_draft.user = :user')->setParameter('user', $filter->user);
|
|
}
|
|
|
|
return $qb;
|
|
}
|
|
|
|
/**
|
|
* The accounts that actually have a draft — the full user table would be an unusable
|
|
* choice list and most of it could never match.
|
|
*
|
|
* @return User[]
|
|
*/
|
|
public function findDraftOwners(): array
|
|
{
|
|
// Rooted at the user rather than the draft: DQL cannot select a joined entity on its own.
|
|
/** @var User[] $users */
|
|
$users = $this->getEntityManager()
|
|
->createQueryBuilder()
|
|
->select('user')
|
|
->distinct()
|
|
->from(User::class, 'user')
|
|
->innerJoin(BookingEditDraft::class, 'draft', Join::ON, 'draft.user = user')
|
|
->orderBy('user.email', 'ASC')
|
|
->getQuery()
|
|
->getResult()
|
|
;
|
|
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* Finds a draft for a specific user and booking combination.
|
|
*
|
|
* @param User $user The user who owns the draft
|
|
* @param int $bookingId The BusProNet booking ID
|
|
*
|
|
* @return BookingEditDraft|null The draft if found, null otherwise
|
|
*/
|
|
public function findByUserAndBooking(User $user, int $bookingId): ?BookingEditDraft
|
|
{
|
|
return $this->findOneBy([
|
|
'user' => $user,
|
|
'bookingId' => $bookingId,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Deletes a draft for a specific user and booking combination.
|
|
*
|
|
* @param User $user The user who owns the draft
|
|
* @param int $bookingId The BusProNet booking ID
|
|
*/
|
|
public function deleteByUserAndBooking(User $user, int $bookingId): void
|
|
{
|
|
$this->createQueryBuilder('d')
|
|
->delete()
|
|
->where('d.user = :user')
|
|
->andWhere('d.bookingId = :bookingId')
|
|
->setParameters(new ArrayCollection([
|
|
new Parameter('user', $user),
|
|
new Parameter('bookingId', $bookingId),
|
|
]))
|
|
->getQuery()
|
|
->execute();
|
|
}
|
|
|
|
/**
|
|
* Deletes all drafts where the travel date has passed.
|
|
*
|
|
* @return int Number of deleted drafts
|
|
*/
|
|
public function deleteExpiredDrafts(): int
|
|
{
|
|
return (int) $this->createQueryBuilder('d')
|
|
->delete()
|
|
->where('d.travelDate < :today')
|
|
->setParameter('today', new \DateTimeImmutable('today'))
|
|
->getQuery()
|
|
->execute();
|
|
}
|
|
}
|