add user preference: default report (#2430)
This commit is contained in:
@@ -14,6 +14,7 @@ use App\Reporting\MonthByUser;
|
||||
use App\Reporting\MonthByUserForm;
|
||||
use App\Reporting\MonthlyUserList;
|
||||
use App\Reporting\MonthlyUserListForm;
|
||||
use App\Reporting\ReportingService;
|
||||
use App\Reporting\WeekByUser;
|
||||
use App\Reporting\WeekByUserForm;
|
||||
use App\Repository\Query\UserQuery;
|
||||
@@ -54,9 +55,33 @@ final class ReportingController extends AbstractController
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function defaultReport(): Response
|
||||
public function defaultReport(ReportingService $reportingService): Response
|
||||
{
|
||||
return $this->redirectToRoute('report_user_week');
|
||||
$user = $this->getUser();
|
||||
$route = null;
|
||||
|
||||
$defaultReport = $user->getPreferenceValue('reporting.initial_view', ReportingService::DEFAULT_VIEW);
|
||||
$allReports = $reportingService->getAvailableReports($user);
|
||||
|
||||
foreach ($allReports as $report) {
|
||||
if ($report->getId() === $defaultReport) {
|
||||
$route = $report->getRoute();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback, if the configured report could not be found
|
||||
// eg. when it was deleted or replaced by an enhanced version with a new id
|
||||
if ($route === null && \count($allReports) > 0) {
|
||||
$report = $allReports[array_keys($allReports)[0]];
|
||||
$route = $report->getRoute();
|
||||
}
|
||||
|
||||
if ($route === null) {
|
||||
throw $this->createNotFoundException('Unknown default report');
|
||||
}
|
||||
|
||||
return $this->redirectToRoute($route);
|
||||
}
|
||||
|
||||
private function canSelectUser(): bool
|
||||
|
||||
@@ -18,8 +18,10 @@ use App\Form\Type\CalendarViewType;
|
||||
use App\Form\Type\FirstWeekDayType;
|
||||
use App\Form\Type\InitialViewType;
|
||||
use App\Form\Type\LanguageType;
|
||||
use App\Form\Type\ReportType;
|
||||
use App\Form\Type\SkinType;
|
||||
use App\Form\Type\ThemeLayoutType;
|
||||
use App\Reporting\ReportingService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
@@ -30,24 +32,15 @@ use Symfony\Component\Validator\Constraints\Range;
|
||||
|
||||
final class UserPreferenceSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
private $eventDispatcher;
|
||||
/**
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
private $voter;
|
||||
/**
|
||||
* @var SystemConfiguration
|
||||
*/
|
||||
private $configuration;
|
||||
|
||||
public function __construct(EventDispatcherInterface $dispatcher, AuthorizationCheckerInterface $voter, SystemConfiguration $formConfig)
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher, AuthorizationCheckerInterface $voter, SystemConfiguration $systemConfiguration)
|
||||
{
|
||||
$this->eventDispatcher = $dispatcher;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->voter = $voter;
|
||||
$this->configuration = $formConfig;
|
||||
$this->configuration = $systemConfiguration;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
@@ -153,6 +146,13 @@ final class UserPreferenceSubscriber implements EventSubscriberInterface
|
||||
->setSection('behaviour')
|
||||
->setType(CalendarViewType::class),
|
||||
|
||||
(new UserPreference())
|
||||
->setName('reporting.initial_view')
|
||||
->setValue(ReportingService::DEFAULT_VIEW)
|
||||
->setOrder(650)
|
||||
->setSection('behaviour')
|
||||
->setType(ReportType::class),
|
||||
|
||||
(new UserPreference())
|
||||
->setName('login.initial_view')
|
||||
->setValue(InitialViewType::DEFAULT_VIEW)
|
||||
|
||||
58
src/Form/Type/ReportType.php
Normal file
58
src/Form/Type/ReportType.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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\Form\Type;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Reporting\ReportingService;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* Custom form field type to select a report.
|
||||
*/
|
||||
class ReportType extends AbstractType
|
||||
{
|
||||
private $reportingService;
|
||||
|
||||
public function __construct(ReportingService $reportingService)
|
||||
{
|
||||
$this->reportingService = $reportingService;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('required', true);
|
||||
$resolver->setDefault('translation_domain', 'reporting');
|
||||
$resolver->setDefault('choices', function (Options $options) {
|
||||
/** @var User $user */
|
||||
$user = $options['user'];
|
||||
|
||||
$choices = [];
|
||||
foreach ($this->reportingService->getAvailableReports($user) as $report) {
|
||||
$choices[$report->getLabel()] = $report->getId();
|
||||
}
|
||||
|
||||
return $choices;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,28 @@ class InvoiceModelDefaultHydrator implements InvoiceModelHydrator
|
||||
$total = $model->getCalculator()->getTotal();
|
||||
$subtotal = $model->getCalculator()->getSubtotal();
|
||||
$formatter = $model->getFormatter();
|
||||
$entries = $model->getCalculator()->getEntries();
|
||||
|
||||
return [
|
||||
$begin = null;
|
||||
if ($model->getQuery()->getBegin() !== null) {
|
||||
$begin = $model->getQuery()->getBegin();
|
||||
} elseif (!empty($entries)) {
|
||||
$begin = $entries[0];
|
||||
}
|
||||
|
||||
$end = null;
|
||||
if ($model->getQuery()->getEnd() !== null) {
|
||||
$end = $model->getQuery()->getEnd();
|
||||
} elseif (!empty($entries)) {
|
||||
$end = array_keys($entries)[\count($entries) - 1];
|
||||
}
|
||||
|
||||
$values = [
|
||||
'invoice.due_date' => $formatter->getFormattedDateTime($model->getDueDate()),
|
||||
'invoice.date' => $formatter->getFormattedDateTime($model->getInvoiceDate()),
|
||||
'invoice.number' => $model->getInvoiceNumber(),
|
||||
'invoice.currency' => $currency,
|
||||
'invoice.language' => $model->getTemplate()->getLanguage(), // since 1.9
|
||||
'invoice.language' => $model->getTemplate()->getLanguage(), // since 1.9
|
||||
'invoice.currency_symbol' => $formatter->getCurrencySymbol($currency),
|
||||
'invoice.vat' => $model->getCalculator()->getVat(),
|
||||
'invoice.tax' => $formatter->getFormattedMoney($tax, $currency),
|
||||
@@ -52,20 +67,41 @@ class InvoiceModelDefaultHydrator implements InvoiceModelHydrator
|
||||
'template.contact' => $model->getTemplate()->getContact(),
|
||||
'template.payment_details' => $model->getTemplate()->getPaymentDetails(),
|
||||
|
||||
'query.begin' => $formatter->getFormattedDateTime($model->getQuery()->getBegin()),
|
||||
'query.day' => $model->getQuery()->getBegin()->format('d'), // @deprecated
|
||||
'query.month' => $formatter->getFormattedMonthName($model->getQuery()->getBegin()), // @deprecated
|
||||
'query.month_number' => $model->getQuery()->getBegin()->format('m'), // @deprecated
|
||||
'query.year' => $model->getQuery()->getBegin()->format('Y'), // @deprecated
|
||||
'query.begin_day' => $model->getQuery()->getBegin()->format('d'),
|
||||
'query.begin_month' => $formatter->getFormattedMonthName($model->getQuery()->getBegin()),
|
||||
'query.begin_month_number' => $model->getQuery()->getBegin()->format('m'),
|
||||
'query.begin_year' => $model->getQuery()->getBegin()->format('Y'),
|
||||
'query.end' => $formatter->getFormattedDateTime($model->getQuery()->getEnd()), // since 1.9
|
||||
'query.end_day' => $model->getQuery()->getEnd()->format('d'), // since 1.9
|
||||
'query.end_month' => $formatter->getFormattedMonthName($model->getQuery()->getEnd()), // since 1.9
|
||||
'query.end_month_number' => $model->getQuery()->getEnd()->format('m'), // since 1.9
|
||||
'query.end_year' => $model->getQuery()->getEnd()->format('Y'), // since 1.9
|
||||
'query.begin' => '',
|
||||
'query.day' => '', // @deprecated
|
||||
'query.month' => '', // @deprecated
|
||||
'query.month_number' => '', // @deprecated
|
||||
'query.year' => '', // @deprecated
|
||||
'query.begin_day' => '',
|
||||
'query.begin_month' => '',
|
||||
'query.begin_month_number' => '',
|
||||
'query.begin_year' => '',
|
||||
'query.end' => '', // since 1.9
|
||||
'query.end_day' => '', // since 1.9
|
||||
'query.end_month' => '', // since 1.9
|
||||
'query.end_month_number' => '', // since 1.9
|
||||
'query.end_year' => '', // since 1.9
|
||||
];
|
||||
|
||||
if ($begin !== null) {
|
||||
$values = array_merge($values, [
|
||||
'query.begin' => $formatter->getFormattedDateTime($begin),
|
||||
'query.day' => $begin->format('d'), // @deprecated
|
||||
'query.month' => $formatter->getFormattedMonthName($begin), // @deprecated
|
||||
'query.month_number' => $begin->format('m'), // @deprecated
|
||||
'query.year' => $begin->format('Y'), // @deprecated
|
||||
'query.begin_day' => $begin->format('d'),
|
||||
'query.begin_month' => $formatter->getFormattedMonthName($begin),
|
||||
'query.begin_month_number' => $begin->format('m'),
|
||||
'query.begin_year' => $begin->format('Y'),
|
||||
'query.end' => $formatter->getFormattedDateTime($end), // since 1.9
|
||||
'query.end_day' => $end->format('d'), // since 1.9
|
||||
'query.end_month' => $formatter->getFormattedMonthName($end), // since 1.9
|
||||
'query.end_month_number' => $end->format('m'), // since 1.9
|
||||
'query.end_year' => $end->format('Y'), // since 1.9
|
||||
]);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,12 @@ final class ProjectViewService
|
||||
}
|
||||
|
||||
if (!$query->isIncludeNoBudget()) {
|
||||
$qb->andWhere($qb->expr()->gt('p.timeBudget', 0));
|
||||
$qb->andWhere(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gt('p.budget', 0),
|
||||
$qb->expr()->gt('p.timeBudget', 0)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->repository->addPermissionCriteria($qb, $user);
|
||||
|
||||
@@ -16,6 +16,8 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
final class ReportingService
|
||||
{
|
||||
public const DEFAULT_VIEW = 'week_by_user';
|
||||
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
@@ -40,7 +42,7 @@ final class ReportingService
|
||||
$event = new ReportingEvent($user);
|
||||
|
||||
if ($this->security->isGranted('view_reporting')) {
|
||||
$event->addReport(new Report('week_by_user', 'report_user_week', 'report_user_week'));
|
||||
$event->addReport(new Report(self::DEFAULT_VIEW, 'report_user_week', 'report_user_week'));
|
||||
$event->addReport(new Report('month_by_user', 'report_user_month', 'report_user_month'));
|
||||
if ($this->security->isGranted('budget_project')) {
|
||||
$event->addReport(new Report('project_view', 'report_project_view', 'report_project_view'));
|
||||
@@ -48,9 +50,9 @@ final class ReportingService
|
||||
if ($this->security->isGranted('view_other_timesheet')) {
|
||||
$event->addReport(new Report('monthly_users_list', 'report_monthly_users', 'report_monthly_users'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->dispatcher->dispatch($event);
|
||||
}
|
||||
|
||||
return $event->getReports();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user