Allow to customize statistic queries (#5827)
* use TimesheetStatisticsQUery for all repository calls * send event to customize statistics query
This commit is contained in:
@@ -16,6 +16,7 @@ use App\Model\DateStatisticInterface;
|
|||||||
use App\Model\Statistic\StatisticDate;
|
use App\Model\Statistic\StatisticDate;
|
||||||
use App\Repository\ActivityRepository;
|
use App\Repository\ActivityRepository;
|
||||||
use App\Repository\ProjectRepository;
|
use App\Repository\ProjectRepository;
|
||||||
|
use App\Repository\Query\TimesheetStatisticQuery;
|
||||||
use App\Timesheet\TimesheetStatisticService;
|
use App\Timesheet\TimesheetStatisticService;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ abstract class AbstractUserReportController extends AbstractController
|
|||||||
|
|
||||||
protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
|
protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
|
||||||
{
|
{
|
||||||
return $this->statisticService->getDailyStatisticsGrouped($begin, $end, [$user]);
|
return $this->statisticService->getDailyStatisticsGrouped(new TimesheetStatisticQuery($begin, $end, [$user]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface
|
protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use App\Model\DateStatisticInterface;
|
|||||||
use App\Model\MonthlyStatistic;
|
use App\Model\MonthlyStatistic;
|
||||||
use App\Reporting\YearByUser\YearByUser;
|
use App\Reporting\YearByUser\YearByUser;
|
||||||
use App\Reporting\YearByUser\YearByUserForm;
|
use App\Reporting\YearByUser\YearByUserForm;
|
||||||
|
use App\Repository\Query\TimesheetStatisticQuery;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||||
@@ -125,7 +126,7 @@ final class UserYearController extends AbstractUserReportController
|
|||||||
|
|
||||||
protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
|
protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
|
||||||
{
|
{
|
||||||
return $this->statisticService->getMonthlyStatisticsGrouped($begin, $end, [$user]);
|
return $this->statisticService->getMonthlyStatisticsGrouped(new TimesheetStatisticQuery($begin, $end, [$user]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface
|
protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface
|
||||||
|
|||||||
25
src/Event/TimesheetStatisticsQueryEvent.php
Normal file
25
src/Event/TimesheetStatisticsQueryEvent.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Event;
|
||||||
|
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Contracts\EventDispatcher\Event;
|
||||||
|
|
||||||
|
final class TimesheetStatisticsQueryEvent extends Event
|
||||||
|
{
|
||||||
|
public function __construct(private readonly QueryBuilder $queryBuilder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryBuilder(): QueryBuilder
|
||||||
|
{
|
||||||
|
return $this->queryBuilder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,15 +10,19 @@
|
|||||||
namespace App\Timesheet;
|
namespace App\Timesheet;
|
||||||
|
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
use App\Event\TimesheetStatisticsQueryEvent;
|
||||||
use App\Model\DailyStatistic;
|
use App\Model\DailyStatistic;
|
||||||
use App\Model\MonthlyStatistic;
|
use App\Model\MonthlyStatistic;
|
||||||
use App\Repository\Query\TimesheetStatisticQuery;
|
use App\Repository\Query\TimesheetStatisticQuery;
|
||||||
use App\Repository\TimesheetRepository;
|
use App\Repository\TimesheetRepository;
|
||||||
use DateTimeInterface;
|
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
||||||
final class TimesheetStatisticService
|
final class TimesheetStatisticService
|
||||||
{
|
{
|
||||||
public function __construct(private readonly TimesheetRepository $repository)
|
public function __construct(
|
||||||
|
private readonly TimesheetRepository $repository,
|
||||||
|
private readonly EventDispatcherInterface $eventDispatcher
|
||||||
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +76,8 @@ final class TimesheetStatisticService
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb));
|
||||||
|
|
||||||
$results = $qb->getQuery()->getResult();
|
$results = $qb->getQuery()->getResult();
|
||||||
|
|
||||||
foreach ($results as $row) {
|
foreach ($results as $row) {
|
||||||
@@ -96,13 +102,14 @@ final class TimesheetStatisticService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal only for core development
|
* @internal only for core development
|
||||||
* @param DateTimeInterface $begin
|
|
||||||
* @param DateTimeInterface $end
|
|
||||||
* @param User[] $users
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getDailyStatisticsGrouped(DateTimeInterface $begin, DateTimeInterface $end, array $users): array
|
public function getDailyStatisticsGrouped(TimesheetStatisticQuery $query): array
|
||||||
{
|
{
|
||||||
|
$begin = $query->getBegin();
|
||||||
|
$end = $query->getEnd();
|
||||||
|
$users = $query->getUsers();
|
||||||
|
|
||||||
$stats = [];
|
$stats = [];
|
||||||
$usersById = [];
|
$usersById = [];
|
||||||
|
|
||||||
@@ -137,6 +144,8 @@ final class TimesheetStatisticService
|
|||||||
->addGroupBy('billable')
|
->addGroupBy('billable')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb));
|
||||||
|
|
||||||
$results = $qb->getQuery()->getResult();
|
$results = $qb->getQuery()->getResult();
|
||||||
|
|
||||||
foreach ($results as $row) {
|
foreach ($results as $row) {
|
||||||
@@ -173,11 +182,14 @@ final class TimesheetStatisticService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal only for core development
|
* @internal only for core development
|
||||||
* @param User[] $users
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getMonthlyStatisticsGrouped(DateTimeInterface $begin, DateTimeInterface $end, array $users): array
|
public function getMonthlyStatisticsGrouped(TimesheetStatisticQuery $query): array
|
||||||
{
|
{
|
||||||
|
$begin = $query->getBegin();
|
||||||
|
$end = $query->getEnd();
|
||||||
|
$users = $query->getUsers();
|
||||||
|
|
||||||
$stats = [];
|
$stats = [];
|
||||||
$usersById = [];
|
$usersById = [];
|
||||||
|
|
||||||
@@ -214,6 +226,8 @@ final class TimesheetStatisticService
|
|||||||
->addGroupBy('billable')
|
->addGroupBy('billable')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb));
|
||||||
|
|
||||||
$results = $qb->getQuery()->getResult();
|
$results = $qb->getQuery()->getResult();
|
||||||
|
|
||||||
foreach ($results as $row) {
|
foreach ($results as $row) {
|
||||||
@@ -311,6 +325,8 @@ final class TimesheetStatisticService
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb));
|
||||||
|
|
||||||
$results = $qb->getQuery()->getResult();
|
$results = $qb->getQuery()->getResult();
|
||||||
|
|
||||||
foreach ($results as $row) {
|
foreach ($results as $row) {
|
||||||
|
|||||||
31
tests/Event/TimesheetStatisticsQueryEventTest.php
Normal file
31
tests/Event/TimesheetStatisticsQueryEventTest.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Event;
|
||||||
|
|
||||||
|
use App\Event\TimesheetStatisticsQueryEvent;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
#[CoversClass(TimesheetStatisticsQueryEvent::class)]
|
||||||
|
class TimesheetStatisticsQueryEventTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testGetter(): void
|
||||||
|
{
|
||||||
|
$qb = new QueryBuilder($this->createMock(EntityManager::class));
|
||||||
|
self::assertCount(0, $qb->getParameters());
|
||||||
|
$sut = new TimesheetStatisticsQueryEvent($qb);
|
||||||
|
$qb->setParameter('foo', 'bar');
|
||||||
|
|
||||||
|
self::assertSame($qb, $sut->getQueryBuilder());
|
||||||
|
self::assertCount(1, $sut->getQueryBuilder()->getParameters());
|
||||||
|
}
|
||||||
|
}
|
||||||
40
tests/Event/WorkingTimeQueryStatsEventTest.php
Normal file
40
tests/Event/WorkingTimeQueryStatsEventTest.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai time-tracking app.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Tests\Event;
|
||||||
|
|
||||||
|
use App\Entity\User;
|
||||||
|
use App\Event\WorkingTimeQueryStatsEvent;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
#[CoversClass(WorkingTimeQueryStatsEvent::class)]
|
||||||
|
class WorkingTimeQueryStatsEventTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testGetter(): void
|
||||||
|
{
|
||||||
|
$qb = new QueryBuilder($this->createMock(EntityManager::class));
|
||||||
|
self::assertCount(0, $qb->getParameters());
|
||||||
|
|
||||||
|
$user = new User();
|
||||||
|
$begin = new \DateTime('2004-02-13');
|
||||||
|
$end = new \DateTime('2099-12-31');
|
||||||
|
|
||||||
|
$sut = new WorkingTimeQueryStatsEvent($qb, $user, $begin, $end);
|
||||||
|
$qb->setParameter('foo', 'bar');
|
||||||
|
|
||||||
|
self::assertSame($qb, $sut->getQueryBuilder());
|
||||||
|
self::assertCount(1, $sut->getQueryBuilder()->getParameters());
|
||||||
|
self::assertSame($user, $sut->getUser());
|
||||||
|
self::assertSame($begin, $sut->getBegin());
|
||||||
|
self::assertSame($end, $sut->getEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user