feat: applications by destination statistics
addresses #869dv9fh6
This commit is contained in:
@@ -7,6 +7,7 @@ use App\Entity\Assignment;
|
||||
use App\Entity\Teamer;
|
||||
use App\Model\ApplicationFilterDto;
|
||||
use App\Model\AssignmentFilterDto;
|
||||
use App\Repository\Filter\SeasonPeriodFilter;
|
||||
use App\Repository\Traits\QueryHelperTrait;
|
||||
use Carbon\CarbonPeriodImmutable;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
@@ -250,4 +251,69 @@ class ApplicationRepository extends ServiceEntityRepository
|
||||
->getSingleScalarResult()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* The raw tally grouped by normalized hotel code, split by application status.
|
||||
*
|
||||
* Mirrors DispositionRepository::getFeedbackStatisticsByNormalizedHotelCodeQuery() - the
|
||||
* "Bewerbungen pro Destination" screen sits next to "Feedback pro Destination" and means the
|
||||
* same thing by a destination and a season, so the normalization and the date filter are the
|
||||
* shared ones.
|
||||
*/
|
||||
public function getApplicationsByDestinationQuery(
|
||||
?\DateTimeImmutable $dateFrom = null,
|
||||
?\DateTimeImmutable $dateTo = null,
|
||||
): Query {
|
||||
$qb = $this->createQueryBuilder('application');
|
||||
|
||||
// Normalize hotel code: strip SER prefix to get base 3-char code
|
||||
$normalizedHotelCode = "CASE WHEN destination.hotelCode LIKE 'SER%' THEN SUBSTRING(destination.hotelCode, 4, 3) ELSE SUBSTRING(destination.hotelCode, 1, 3) END";
|
||||
|
||||
$qb
|
||||
->select(
|
||||
$normalizedHotelCode.' AS hotelCode',
|
||||
'SUM(CASE WHEN application.status = :statusNew THEN 1 ELSE 0 END) AS newCount',
|
||||
'SUM(CASE WHEN application.status = :statusPending THEN 1 ELSE 0 END) AS pendingCount',
|
||||
'SUM(CASE WHEN application.status = :statusRejected THEN 1 ELSE 0 END) AS rejectedCount',
|
||||
'COUNT(application.id) AS totalCount'
|
||||
)
|
||||
->innerJoin('application.assignment', 'assignment')
|
||||
->innerJoin('assignment.destination', 'destination')
|
||||
->setParameter('statusNew', Application::STATUS_NEW)
|
||||
->setParameter('statusPending', Application::STATUS_PENDING)
|
||||
->setParameter('statusRejected', Application::STATUS_REJECTED)
|
||||
->groupBy('hotelCode')
|
||||
->orderBy('totalCount', 'DESC')
|
||||
->addOrderBy('hotelCode', 'ASC')
|
||||
;
|
||||
|
||||
SeasonPeriodFilter::apply($qb, $dateFrom, $dateTo);
|
||||
|
||||
return $qb->getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns application counts grouped by normalized hotel code (base 3-char code),
|
||||
* split into the three application statuses plus a total.
|
||||
*
|
||||
* @return array<int, array{
|
||||
* hotelCode: string,
|
||||
* new: int,
|
||||
* pending: int,
|
||||
* rejected: int,
|
||||
* total: int
|
||||
* }>
|
||||
*/
|
||||
public function getApplicationsByDestination(
|
||||
?\DateTimeImmutable $dateFrom = null,
|
||||
?\DateTimeImmutable $dateTo = null,
|
||||
): array {
|
||||
return array_map(static fn (array $row): array => [
|
||||
'hotelCode' => $row['hotelCode'],
|
||||
'new' => (int) $row['newCount'],
|
||||
'pending' => (int) $row['pendingCount'],
|
||||
'rejected' => (int) $row['rejectedCount'],
|
||||
'total' => (int) $row['totalCount'],
|
||||
], $this->getApplicationsByDestinationQuery($dateFrom, $dateTo)->getResult());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user