use events for budget calculation (#2544)
This commit is contained in:
40
src/Activity/ActivityStatisticService.php
Normal file
40
src/Activity/ActivityStatisticService.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\Activity;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Event\ActivityStatisticEvent;
|
||||
use App\Model\ActivityStatistic;
|
||||
use App\Repository\ActivityRepository;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class ActivityStatisticService
|
||||
{
|
||||
private $repository;
|
||||
private $dispatcher;
|
||||
|
||||
public function __construct(ActivityRepository $activityRepository, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->repository = $activityRepository;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function getActivityStatistics(Activity $activity): ActivityStatistic
|
||||
{
|
||||
$statistic = $this->repository->getActivityStatistics($activity);
|
||||
$event = new ActivityStatisticEvent($activity, $statistic);
|
||||
$this->dispatcher->dispatch($event);
|
||||
|
||||
return $statistic;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Activity\ActivityService;
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\ActivityRate;
|
||||
@@ -114,7 +115,7 @@ final class ActivityController extends AbstractController
|
||||
* @Route(path="/{id}/details", name="activity_details", methods={"GET", "POST"})
|
||||
* @Security("is_granted('view', activity)")
|
||||
*/
|
||||
public function detailsAction(Activity $activity, TeamRepository $teamRepository, ActivityRateRepository $rateRepository)
|
||||
public function detailsAction(Activity $activity, TeamRepository $teamRepository, ActivityRateRepository $rateRepository, ActivityStatisticService $statisticService)
|
||||
{
|
||||
$event = new ActivityMetaDefinitionEvent($activity);
|
||||
$this->dispatcher->dispatch($event);
|
||||
@@ -132,7 +133,7 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
|
||||
if ($this->isGranted('budget', $activity)) {
|
||||
$stats = $this->repository->getActivityStatistics($activity);
|
||||
$stats = $statisticService->getActivityStatistics($activity);
|
||||
}
|
||||
|
||||
if ($this->isGranted('permissions', $activity) || $this->isGranted('details', $activity) || $this->isGranted('view_team')) {
|
||||
@@ -308,9 +309,9 @@ final class ActivityController extends AbstractController
|
||||
* @Route(path="/{id}/delete", name="admin_activity_delete", methods={"GET", "POST"})
|
||||
* @Security("is_granted('delete', activity)")
|
||||
*/
|
||||
public function deleteAction(Activity $activity, Request $request)
|
||||
public function deleteAction(Activity $activity, Request $request, ActivityStatisticService $statisticService)
|
||||
{
|
||||
$stats = $this->repository->getActivityStatistics($activity);
|
||||
$stats = $statisticService->getActivityStatistics($activity);
|
||||
|
||||
$deleteForm = $this->createFormBuilder(null, [
|
||||
'attr' => [
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Customer\CustomerStatisticService;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\CustomerComment;
|
||||
use App\Entity\CustomerRate;
|
||||
@@ -268,7 +269,7 @@ final class CustomerController extends AbstractController
|
||||
* @Route(path="/{id}/details", name="customer_details", methods={"GET", "POST"})
|
||||
* @Security("is_granted('view', customer)")
|
||||
*/
|
||||
public function detailsAction(Customer $customer, TeamRepository $teamRepository, CustomerRateRepository $rateRepository)
|
||||
public function detailsAction(Customer $customer, TeamRepository $teamRepository, CustomerRateRepository $rateRepository, CustomerStatisticService $statisticService)
|
||||
{
|
||||
$event = new CustomerMetaDefinitionEvent($customer);
|
||||
$this->dispatcher->dispatch($event);
|
||||
@@ -295,7 +296,7 @@ final class CustomerController extends AbstractController
|
||||
}
|
||||
|
||||
if ($this->isGranted('budget', $customer)) {
|
||||
$stats = $this->repository->getCustomerStatistics($customer);
|
||||
$stats = $statisticService->getCustomerStatistics($customer);
|
||||
}
|
||||
|
||||
if ($this->isGranted('comments', $customer)) {
|
||||
@@ -370,9 +371,9 @@ final class CustomerController extends AbstractController
|
||||
* @Route(path="/{id}/delete", name="admin_customer_delete", methods={"GET", "POST"})
|
||||
* @Security("is_granted('delete', customer)")
|
||||
*/
|
||||
public function deleteAction(Customer $customer, Request $request)
|
||||
public function deleteAction(Customer $customer, Request $request, CustomerStatisticService $statisticService)
|
||||
{
|
||||
$stats = $this->repository->getCustomerStatistics($customer);
|
||||
$stats = $statisticService->getCustomerStatistics($customer);
|
||||
|
||||
$deleteForm = $this->createFormBuilder(null, [
|
||||
'attr' => [
|
||||
|
||||
@@ -30,6 +30,7 @@ use App\Form\Toolbar\ProjectToolbarForm;
|
||||
use App\Form\Type\ProjectType;
|
||||
use App\Project\ProjectDuplicationService;
|
||||
use App\Project\ProjectService;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\ActivityRepository;
|
||||
use App\Repository\ProjectRateRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
@@ -291,7 +292,7 @@ final class ProjectController extends AbstractController
|
||||
* @Route(path="/{id}/details", name="project_details", methods={"GET", "POST"})
|
||||
* @Security("is_granted('view', project)")
|
||||
*/
|
||||
public function detailsAction(Project $project, TeamRepository $teamRepository, ProjectRateRepository $rateRepository)
|
||||
public function detailsAction(Project $project, TeamRepository $teamRepository, ProjectRateRepository $rateRepository, ProjectStatisticService $statisticService)
|
||||
{
|
||||
$event = new ProjectMetaDefinitionEvent($project);
|
||||
$this->dispatcher->dispatch($event);
|
||||
@@ -312,7 +313,7 @@ final class ProjectController extends AbstractController
|
||||
}
|
||||
|
||||
if ($this->isGranted('budget', $project)) {
|
||||
$stats = $this->repository->getProjectStatistics($project);
|
||||
$stats = $statisticService->getProjectStatistics($project);
|
||||
}
|
||||
|
||||
if ($this->isGranted('comments', $project)) {
|
||||
@@ -414,9 +415,9 @@ final class ProjectController extends AbstractController
|
||||
* @Route(path="/{id}/delete", name="admin_project_delete", methods={"GET", "POST"})
|
||||
* @Security("is_granted('delete', project)")
|
||||
*/
|
||||
public function deleteAction(Project $project, Request $request)
|
||||
public function deleteAction(Project $project, Request $request, ProjectStatisticService $statisticService)
|
||||
{
|
||||
$stats = $this->repository->getProjectStatistics($project);
|
||||
$stats = $statisticService->getProjectStatistics($project);
|
||||
|
||||
$deleteForm = $this->createFormBuilder(null, [
|
||||
'attr' => [
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
namespace App\Controller\Reporting;
|
||||
|
||||
use App\Controller\AbstractController;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Reporting\ProjectInactive\ProjectInactiveForm;
|
||||
use App\Reporting\ProjectInactive\ProjectInactiveQuery;
|
||||
use App\Reporting\ProjectStatisticService;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Controller\Reporting;
|
||||
|
||||
use App\Controller\AbstractController;
|
||||
use App\Reporting\ProjectStatisticService;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Reporting\ProjectView\ProjectViewForm;
|
||||
use App\Reporting\ProjectView\ProjectViewQuery;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
|
||||
40
src/Customer/CustomerStatisticService.php
Normal file
40
src/Customer/CustomerStatisticService.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\Customer;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\CustomerStatisticEvent;
|
||||
use App\Model\CustomerStatistic;
|
||||
use App\Repository\CustomerRepository;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class CustomerStatisticService
|
||||
{
|
||||
private $repository;
|
||||
private $dispatcher;
|
||||
|
||||
public function __construct(CustomerRepository $customerRepository, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->repository = $customerRepository;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function getCustomerStatistics(Customer $customer): CustomerStatistic
|
||||
{
|
||||
$statistic = $this->repository->getCustomerStatistics($customer);
|
||||
$event = new CustomerStatisticEvent($customer, $statistic);
|
||||
$this->dispatcher->dispatch($event);
|
||||
|
||||
return $statistic;
|
||||
}
|
||||
}
|
||||
29
src/Event/ActivityStatisticEvent.php
Normal file
29
src/Event/ActivityStatisticEvent.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?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 App\Entity\Activity;
|
||||
use App\Model\ActivityStatistic;
|
||||
|
||||
final class ActivityStatisticEvent extends AbstractActivityEvent
|
||||
{
|
||||
private $statistic;
|
||||
|
||||
public function __construct(Activity $activity, ActivityStatistic $statistic)
|
||||
{
|
||||
parent::__construct($activity);
|
||||
$this->statistic = $statistic;
|
||||
}
|
||||
|
||||
public function getStatistic(): ActivityStatistic
|
||||
{
|
||||
return $this->statistic;
|
||||
}
|
||||
}
|
||||
29
src/Event/CustomerStatisticEvent.php
Normal file
29
src/Event/CustomerStatisticEvent.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?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 App\Entity\Customer;
|
||||
use App\Model\CustomerStatistic;
|
||||
|
||||
final class CustomerStatisticEvent extends AbstractCustomerEvent
|
||||
{
|
||||
private $statistic;
|
||||
|
||||
public function __construct(Customer $customer, CustomerStatistic $statistic)
|
||||
{
|
||||
parent::__construct($customer);
|
||||
$this->statistic = $statistic;
|
||||
}
|
||||
|
||||
public function getStatistic(): CustomerStatistic
|
||||
{
|
||||
return $this->statistic;
|
||||
}
|
||||
}
|
||||
29
src/Event/ProjectStatisticEvent.php
Normal file
29
src/Event/ProjectStatisticEvent.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?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 App\Entity\Project;
|
||||
use App\Model\ProjectStatistic;
|
||||
|
||||
final class ProjectStatisticEvent extends AbstractProjectEvent
|
||||
{
|
||||
private $statistic;
|
||||
|
||||
public function __construct(Project $project, ProjectStatistic $statistic)
|
||||
{
|
||||
parent::__construct($project);
|
||||
$this->statistic = $statistic;
|
||||
}
|
||||
|
||||
public function getStatistic(): ProjectStatistic
|
||||
{
|
||||
return $this->statistic;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ use App\Event\ProjectMetaDisplayEvent;
|
||||
use App\Event\TimesheetMetaDisplayEvent;
|
||||
use App\Event\UserPreferenceDisplayEvent;
|
||||
use App\Export\ExportItemInterface;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\Query\CustomerQuery;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
@@ -37,9 +37,9 @@ class HtmlRenderer
|
||||
*/
|
||||
protected $dispatcher;
|
||||
/**
|
||||
* @var ProjectRepository
|
||||
* @var ProjectStatisticService
|
||||
*/
|
||||
private $projectRepository;
|
||||
private $projectStatisticService;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -49,11 +49,11 @@ class HtmlRenderer
|
||||
*/
|
||||
private $template = 'default.html.twig';
|
||||
|
||||
public function __construct(Environment $twig, EventDispatcherInterface $dispatcher, ProjectRepository $projectRepository)
|
||||
public function __construct(Environment $twig, EventDispatcherInterface $dispatcher, ProjectStatisticService $projectStatisticService)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->projectRepository = $projectRepository;
|
||||
$this->projectStatisticService = $projectStatisticService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ class HtmlRenderer
|
||||
'entries' => $timesheets,
|
||||
'query' => $query,
|
||||
'summaries' => $summary,
|
||||
'budgets' => $this->calculateProjectBudget($timesheets, $query, $this->projectRepository),
|
||||
'budgets' => $this->calculateProjectBudget($timesheets, $query, $this->projectStatisticService),
|
||||
// @deprecated since 1.3, will be removed with 2.0
|
||||
'metaColumns' => $timesheetMetaFields,
|
||||
'timesheetMetaFields' => $timesheetMetaFields,
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace App\Export\Base;
|
||||
|
||||
use App\Export\ExportContext;
|
||||
use App\Export\ExportItemInterface;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
use App\Utils\FileHelper;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
@@ -32,9 +32,9 @@ class PDFRenderer
|
||||
*/
|
||||
private $converter;
|
||||
/**
|
||||
* @var ProjectRepository
|
||||
* @var ProjectStatisticService
|
||||
*/
|
||||
private $projectRepository;
|
||||
private $projectStatisticService;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -48,11 +48,11 @@ class PDFRenderer
|
||||
*/
|
||||
private $pdfOptions = [];
|
||||
|
||||
public function __construct(Environment $twig, HtmlToPdfConverter $converter, ProjectRepository $projectRepository)
|
||||
public function __construct(Environment $twig, HtmlToPdfConverter $converter, ProjectStatisticService $projectRepository)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->converter = $converter;
|
||||
$this->projectRepository = $projectRepository;
|
||||
$this->projectStatisticService = $projectRepository;
|
||||
}
|
||||
|
||||
protected function getTemplate(): string
|
||||
@@ -104,7 +104,7 @@ class PDFRenderer
|
||||
// @deprecated since 1.13
|
||||
'now' => new \DateTime('now', new \DateTimeZone(date_default_timezone_get())),
|
||||
'summaries' => $summary,
|
||||
'budgets' => $this->calculateProjectBudget($timesheets, $query, $this->projectRepository),
|
||||
'budgets' => $this->calculateProjectBudget($timesheets, $query, $this->projectStatisticService),
|
||||
'decimal' => false,
|
||||
'pdfContext' => $context
|
||||
], $this->getOptions($query)));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Export\Base;
|
||||
|
||||
use App\Export\ExportItemInterface;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
|
||||
trait RendererTrait
|
||||
@@ -124,10 +124,10 @@ trait RendererTrait
|
||||
/**
|
||||
* @param ExportItemInterface[] $exportItems
|
||||
* @param TimesheetQuery $query
|
||||
* @param ProjectRepository $projectRepository
|
||||
* @param ProjectStatisticService $projectStatisticService
|
||||
* @return array
|
||||
*/
|
||||
protected function calculateProjectBudget(array $exportItems, TimesheetQuery $query, ProjectRepository $projectRepository)
|
||||
protected function calculateProjectBudget(array $exportItems, TimesheetQuery $query, ProjectStatisticService $projectStatisticService)
|
||||
{
|
||||
$summary = [];
|
||||
|
||||
@@ -154,7 +154,7 @@ trait RendererTrait
|
||||
];
|
||||
|
||||
if (null !== $project && ($project->getTimeBudget() > 0 || $project->getBudget() > 0)) {
|
||||
$projectStats = $projectRepository->getProjectStatistics($project, null, $query->getEnd());
|
||||
$projectStats = $projectStatisticService->getProjectStatistics($project, $query->getEnd());
|
||||
|
||||
if ($project->getTimeBudget() > 0) {
|
||||
$summary[$id]['time_left'] = $project->getTimeBudget() - $projectStats->getRecordDuration();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace App\Export\Renderer;
|
||||
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
@@ -24,20 +24,20 @@ final class HtmlRendererFactory
|
||||
*/
|
||||
private $dispatcher;
|
||||
/**
|
||||
* @var ProjectRepository
|
||||
* @var ProjectStatisticService
|
||||
*/
|
||||
private $projectRepository;
|
||||
private $projectStatisticService;
|
||||
|
||||
public function __construct(Environment $twig, EventDispatcherInterface $dispatcher, ProjectRepository $projectRepository)
|
||||
public function __construct(Environment $twig, EventDispatcherInterface $dispatcher, ProjectStatisticService $projectStatisticService)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->projectRepository = $projectRepository;
|
||||
$this->projectStatisticService = $projectStatisticService;
|
||||
}
|
||||
|
||||
public function create(string $id, string $template): HtmlRenderer
|
||||
{
|
||||
$renderer = new HtmlRenderer($this->twig, $this->dispatcher, $this->projectRepository);
|
||||
$renderer = new HtmlRenderer($this->twig, $this->dispatcher, $this->projectStatisticService);
|
||||
$renderer->setId($id);
|
||||
$renderer->setTemplate($template);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace App\Export\Renderer;
|
||||
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use Twig\Environment;
|
||||
|
||||
@@ -24,20 +24,20 @@ final class PdfRendererFactory
|
||||
*/
|
||||
private $converter;
|
||||
/**
|
||||
* @var ProjectRepository
|
||||
* @var ProjectStatisticService
|
||||
*/
|
||||
private $projectRepository;
|
||||
private $projectStatisticService;
|
||||
|
||||
public function __construct(Environment $twig, HtmlToPdfConverter $converter, ProjectRepository $projectRepository)
|
||||
public function __construct(Environment $twig, HtmlToPdfConverter $converter, ProjectStatisticService $projectStatisticService)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->converter = $converter;
|
||||
$this->projectRepository = $projectRepository;
|
||||
$this->projectStatisticService = $projectStatisticService;
|
||||
}
|
||||
|
||||
public function create(string $id, string $template): PDFRenderer
|
||||
{
|
||||
$renderer = new PDFRenderer($this->twig, $this->converter, $this->projectRepository);
|
||||
$renderer = new PDFRenderer($this->twig, $this->converter, $this->projectStatisticService);
|
||||
$renderer->setId($id);
|
||||
$renderer->setTemplate($template);
|
||||
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Reporting;
|
||||
namespace App\Project;
|
||||
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Event\ProjectStatisticEvent;
|
||||
use App\Model\ProjectStatistic;
|
||||
use App\Reporting\ProjectInactive\ProjectInactiveQuery;
|
||||
use App\Reporting\ProjectView\ProjectViewModel;
|
||||
use App\Reporting\ProjectView\ProjectViewQuery;
|
||||
@@ -20,16 +22,31 @@ use App\Repository\TimesheetRepository;
|
||||
use App\Timesheet\DateTimeFactory;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
final class ProjectStatisticService
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
class ProjectStatisticService
|
||||
{
|
||||
private $repository;
|
||||
private $timesheetRepository;
|
||||
private $dispatcher;
|
||||
|
||||
public function __construct(ProjectRepository $projectRepository, TimesheetRepository $timesheetRepository)
|
||||
public function __construct(ProjectRepository $projectRepository, TimesheetRepository $timesheetRepository, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->repository = $projectRepository;
|
||||
$this->timesheetRepository = $timesheetRepository;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function getProjectStatistics(Project $project, ?DateTime $end = null): ProjectStatistic
|
||||
{
|
||||
$statistic = $this->repository->getProjectStatistics($project, null, $end);
|
||||
$event = new ProjectStatisticEvent($project, $statistic);
|
||||
$this->dispatcher->dispatch($event);
|
||||
|
||||
return $statistic;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +92,7 @@ class ActivityRepository extends EntityRepository
|
||||
* @param Activity $activity
|
||||
* @return ActivityStatistic
|
||||
*/
|
||||
public function getActivityStatistics(Activity $activity)
|
||||
public function getActivityStatistics(Activity $activity): ActivityStatistic
|
||||
{
|
||||
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||
$qb
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
namespace App\Validator;
|
||||
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Customer\CustomerStatisticService;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Repository\ActivityRepository;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Timesheet\RateServiceInterface;
|
||||
use App\Utils\Duration;
|
||||
@@ -25,19 +25,19 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
final class TimesheetBudgetUsedValidator extends ConstraintValidator
|
||||
{
|
||||
private $customerRepository;
|
||||
private $projectRepository;
|
||||
private $activityRepository;
|
||||
private $customerStatisticService;
|
||||
private $projectStatisticService;
|
||||
private $activityStatisticService;
|
||||
private $timesheetRepository;
|
||||
private $rateService;
|
||||
private $configuration;
|
||||
|
||||
public function __construct(SystemConfiguration $configuration, CustomerRepository $customerRepository, ProjectRepository $projectRepository, ActivityRepository $activityRepository, TimesheetRepository $timesheetRepository, RateServiceInterface $rateService)
|
||||
public function __construct(SystemConfiguration $configuration, CustomerStatisticService $customerStatisticService, ProjectStatisticService $projectStatisticService, ActivityStatisticService $activityStatisticService, TimesheetRepository $timesheetRepository, RateServiceInterface $rateService)
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
$this->customerRepository = $customerRepository;
|
||||
$this->projectRepository = $projectRepository;
|
||||
$this->activityRepository = $activityRepository;
|
||||
$this->customerStatisticService = $customerStatisticService;
|
||||
$this->projectStatisticService = $projectStatisticService;
|
||||
$this->activityStatisticService = $activityStatisticService;
|
||||
$this->timesheetRepository = $timesheetRepository;
|
||||
$this->rateService = $rateService;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ final class TimesheetBudgetUsedValidator extends ConstraintValidator
|
||||
return false;
|
||||
}
|
||||
|
||||
$stat = $this->activityRepository->getActivityStatistics($activity);
|
||||
$stat = $this->activityStatisticService->getActivityStatistics($activity);
|
||||
|
||||
$fullRate = ($stat->getRecordRate() + $rate);
|
||||
|
||||
@@ -164,7 +164,7 @@ final class TimesheetBudgetUsedValidator extends ConstraintValidator
|
||||
return false;
|
||||
}
|
||||
|
||||
$stat = $this->projectRepository->getProjectStatistics($project);
|
||||
$stat = $this->projectStatisticService->getProjectStatistics($project);
|
||||
|
||||
$fullRate = ($stat->getRecordRate() + $rate);
|
||||
|
||||
@@ -193,7 +193,7 @@ final class TimesheetBudgetUsedValidator extends ConstraintValidator
|
||||
return false;
|
||||
}
|
||||
|
||||
$stat = $this->customerRepository->getCustomerStatistics($customer);
|
||||
$stat = $this->customerStatisticService->getCustomerStatistics($customer);
|
||||
|
||||
$fullRate = ($stat->getRecordRate() + $rate);
|
||||
|
||||
|
||||
@@ -12,21 +12,18 @@ namespace App\Widget\Type;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
|
||||
class UserTeamProjects extends SimpleWidget implements AuthorizedWidget, UserWidget
|
||||
{
|
||||
/**
|
||||
* @var ProjectRepository
|
||||
*/
|
||||
private $repository;
|
||||
private $statisticService;
|
||||
|
||||
public function __construct(ProjectRepository $repository)
|
||||
public function __construct(ProjectStatisticService $statisticService)
|
||||
{
|
||||
$this->setId('UserTeamProjects');
|
||||
$this->setTitle('label.my_team_projects');
|
||||
$this->setOption('id', '');
|
||||
$this->repository = $repository;
|
||||
$this->statisticService = $statisticService;
|
||||
}
|
||||
|
||||
public function getOptions(array $options = []): array
|
||||
@@ -65,7 +62,7 @@ class UserTeamProjects extends SimpleWidget implements AuthorizedWidget, UserWid
|
||||
if ($project->getBudget() > 0 || $project->getTimeBudget() > 0) {
|
||||
$stats[] = [
|
||||
'project' => $project,
|
||||
'stats' => $this->repository->getProjectStatistics($project),
|
||||
'stats' => $this->statisticService->getProjectStatistics($project),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
36
tests/Event/ActivityStatisticEventTest.php
Normal file
36
tests/Event/ActivityStatisticEventTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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\Activity;
|
||||
use App\Event\AbstractActivityEvent;
|
||||
use App\Event\ActivityStatisticEvent;
|
||||
use App\Model\ActivityStatistic;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractActivityEvent
|
||||
* @covers \App\Event\ActivityStatisticEvent
|
||||
*/
|
||||
class ActivityStatisticEventTest extends AbstractActivityEventTest
|
||||
{
|
||||
protected function createActivityEvent(Activity $activity): AbstractActivityEvent
|
||||
{
|
||||
return new ActivityStatisticEvent($activity, new ActivityStatistic());
|
||||
}
|
||||
|
||||
public function testStatistic()
|
||||
{
|
||||
$activity = new Activity();
|
||||
$statistic = new ActivityStatistic();
|
||||
$sut = new ActivityStatisticEvent($activity, $statistic);
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
}
|
||||
}
|
||||
36
tests/Event/CustomerStatisticEventTest.php
Normal file
36
tests/Event/CustomerStatisticEventTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use App\Event\CustomerStatisticEvent;
|
||||
use App\Model\CustomerStatistic;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractCustomerEvent
|
||||
* @covers \App\Event\CustomerStatisticEvent
|
||||
*/
|
||||
class CustomerStatisticEventTest extends AbstractCustomerEventTest
|
||||
{
|
||||
protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent
|
||||
{
|
||||
return new CustomerStatisticEvent($customer, new CustomerStatistic());
|
||||
}
|
||||
|
||||
public function testStatistic()
|
||||
{
|
||||
$customer = new Customer();
|
||||
$statistic = new CustomerStatistic();
|
||||
$sut = new CustomerStatisticEvent($customer, $statistic);
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
}
|
||||
}
|
||||
36
tests/Event/ProjectStatisticEventTest.php
Normal file
36
tests/Event/ProjectStatisticEventTest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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\Project;
|
||||
use App\Event\AbstractProjectEvent;
|
||||
use App\Event\ProjectStatisticEvent;
|
||||
use App\Model\ProjectStatistic;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractProjectEvent
|
||||
* @covers \App\Event\ProjectStatisticEvent
|
||||
*/
|
||||
class ProjectStatisticEventTest extends AbstractProjectEventTest
|
||||
{
|
||||
protected function createProjectEvent(Project $project): AbstractProjectEvent
|
||||
{
|
||||
return new ProjectStatisticEvent($project, new ProjectStatistic());
|
||||
}
|
||||
|
||||
public function testStatistic()
|
||||
{
|
||||
$project = new Project();
|
||||
$statistic = new ProjectStatistic();
|
||||
$sut = new ProjectStatisticEvent($project, $statistic);
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Export\Renderer\HtmlRenderer;
|
||||
use App\Export\Renderer\HtmlRendererFactory;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Twig\Environment;
|
||||
@@ -26,7 +26,7 @@ class HtmlRendererFactoryTest extends TestCase
|
||||
$sut = new HtmlRendererFactory(
|
||||
$this->createMock(Environment::class),
|
||||
$this->createMock(EventDispatcherInterface::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
);
|
||||
|
||||
$renderer = $sut->create('foo', 'bar.html.twig');
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Export\Renderer\HtmlRenderer;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Twig\Environment;
|
||||
@@ -28,7 +28,7 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$sut = new HtmlRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
);
|
||||
|
||||
$this->assertEquals('html', $sut->getId());
|
||||
@@ -46,7 +46,7 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new HtmlRenderer($twig, new EventDispatcher(), $this->createMock(ProjectRepository::class));
|
||||
$sut = new HtmlRenderer($twig, new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Export\Renderer\PDFRenderer;
|
||||
use App\Export\Renderer\PdfRendererFactory;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Twig\Environment;
|
||||
@@ -26,7 +26,7 @@ class PdfRendererFactoryTest extends TestCase
|
||||
$sut = new PdfRendererFactory(
|
||||
$this->createMock(Environment::class),
|
||||
$this->createMock(HtmlToPdfConverter::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
);
|
||||
|
||||
$renderer = $sut->create('foo', 'bar.pdf.twig');
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Export\Renderer\PDFRenderer;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use App\Utils\MPdfConverter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -29,7 +29,7 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$sut = new PDFRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
$this->createMock(HtmlToPdfConverter::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
);
|
||||
|
||||
$this->assertEquals('pdf', $sut->getId());
|
||||
@@ -54,7 +54,7 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new PDFRenderer($twig, $converter, $this->createMock(ProjectRepository::class));
|
||||
$sut = new PDFRenderer($twig, $converter, $this->createMock(ProjectStatisticService::class));
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Tests\Export;
|
||||
use App\Export\Renderer\HtmlRenderer;
|
||||
use App\Export\ServiceExport;
|
||||
use App\Export\Timesheet\HtmlRenderer as HtmlExporter;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Twig\Environment;
|
||||
@@ -37,7 +37,7 @@ class ServiceExportTest extends TestCase
|
||||
{
|
||||
$sut = new ServiceExport();
|
||||
|
||||
$renderer = new HtmlRenderer($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectRepository::class));
|
||||
$renderer = new HtmlRenderer($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
$sut->addRenderer($renderer);
|
||||
|
||||
self::assertEquals(1, \count($sut->getRenderer()));
|
||||
@@ -48,7 +48,7 @@ class ServiceExportTest extends TestCase
|
||||
{
|
||||
$sut = new ServiceExport();
|
||||
|
||||
$exporter = new HtmlExporter($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectRepository::class));
|
||||
$exporter = new HtmlExporter($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
$sut->addTimesheetExporter($exporter);
|
||||
|
||||
self::assertEquals(1, \count($sut->getTimesheetExporter()));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Export\Timesheet;
|
||||
|
||||
use App\Export\Timesheet\HtmlRenderer;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Twig\Environment;
|
||||
@@ -26,7 +26,7 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$sut = new HtmlRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
);
|
||||
|
||||
$this->assertEquals('print', $sut->getId());
|
||||
@@ -42,7 +42,7 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new HtmlRenderer($twig, new EventDispatcher(), $this->createMock(ProjectRepository::class));
|
||||
$sut = new HtmlRenderer($twig, new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Export\Timesheet;
|
||||
|
||||
use App\Export\Timesheet\PDFRenderer;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Utils\HtmlToPdfConverter;
|
||||
use App\Utils\MPdfConverter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -29,7 +29,7 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$sut = new PDFRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
$this->createMock(HtmlToPdfConverter::class),
|
||||
$this->createMock(ProjectRepository::class)
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
);
|
||||
|
||||
$this->assertEquals('pdf', $sut->getId());
|
||||
@@ -47,7 +47,7 @@ class PdfRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new PDFRenderer($twig, $converter, $this->createMock(ProjectRepository::class));
|
||||
$sut = new PDFRenderer($twig, $converter, $this->createMock(ProjectStatisticService::class));
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
namespace App\Tests\Validator;
|
||||
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Customer\CustomerStatisticService;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
@@ -18,9 +20,7 @@ use App\Entity\User;
|
||||
use App\Model\ActivityStatistic;
|
||||
use App\Model\CustomerStatistic;
|
||||
use App\Model\ProjectStatistic;
|
||||
use App\Repository\ActivityRepository;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Timesheet\Rate;
|
||||
use App\Timesheet\RateService;
|
||||
@@ -43,15 +43,15 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
$configuration = $this->createMock(SystemConfiguration::class);
|
||||
$configuration->method('isTimesheetAllowOverbookingBudget')->willReturn($isAllowed);
|
||||
|
||||
$customerRepository = $this->createMock(CustomerRepository::class);
|
||||
$customerRepository = $this->createMock(CustomerStatisticService::class);
|
||||
$customerStatistic = $customerStatistic ?? new CustomerStatistic();
|
||||
$customerRepository->method('getCustomerStatistics')->willReturn($customerStatistic);
|
||||
|
||||
$projectRepository = $this->createMock(ProjectRepository::class);
|
||||
$projectRepository = $this->createMock(ProjectStatisticService::class);
|
||||
$projectStatistic = $projectStatistic ?? new ProjectStatistic();
|
||||
$projectRepository->method('getProjectStatistics')->willReturn($projectStatistic);
|
||||
|
||||
$activityRepository = $this->createMock(ActivityRepository::class);
|
||||
$activityRepository = $this->createMock(ActivityStatisticService::class);
|
||||
$activityStatistic = $activityStatistic ?? new ActivityStatistic();
|
||||
$activityRepository->method('getActivityStatistics')->willReturn($activityStatistic);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user