add user preference: default report (#2430)

This commit is contained in:
Kevin Papst
2021-03-14 13:32:47 +01:00
committed by GitHub
parent 0a6ea6be42
commit c0378b4f51
16 changed files with 264 additions and 57 deletions

View File

@@ -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

View File

@@ -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)

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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();
}