Release 2.0.18 (#4003)

* prevent too long values for user preferences
* add chart value 0 to y-axis if last value > 0, to always display the zero line (project details)
* add user-preferences to invoice hydrator
* DateTime vs DateTimeInterface
* simplify permission config
* fix query for teamleads limiting to only selected teams not possible
This commit is contained in:
Kevin Papst
2023-05-08 17:11:55 +02:00
committed by GitHub
parent d8f72b8b88
commit 1099e76244
74 changed files with 627 additions and 621 deletions

View File

@@ -20,6 +20,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as BaseAbstract
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
@@ -47,19 +48,41 @@ abstract class AbstractController extends BaseAbstractController implements Serv
return $this->container->get('translator');
}
protected function createSearchForm(string $type = FormType::class, $data = null, array $options = []): FormInterface
/**
* @template TFormType of FormTypeInterface<TData>
* @template TData of mixed
* @param class-string<TFormType> $type
* @param TData $data
* @param array<mixed> $options
* @return FormInterface<TData>
*/
protected function createSearchForm(string $type, mixed $data, array $options = []): FormInterface
{
return $this->createFormForGetRequest($type, $data, $options);
}
protected function createFormForGetRequest(string $type = FormType::class, $data = null, array $options = []): FormInterface
/**
* @template TFormType of FormTypeInterface<TData>
* @template TData of mixed
* @param class-string<TFormType> $type
* @param TData $data
* @param array<mixed> $options
* @return FormInterface<TData>
*/
protected function createFormForGetRequest(string $type, mixed $data, array $options = []): FormInterface
{
return $this->container
->get('form.factory')
->createNamed('', $type, $data, array_merge(['method' => 'GET'], $options));
return $this->container->get('form.factory')->createNamed('', $type, $data, array_merge(['method' => 'GET'], $options)); // @phpstan-ignore-line
}
protected function createFormWithName(string $name, string $type, mixed $data = null, array $options = []): FormInterface
/**
* @template TFormType of FormTypeInterface<TData>
* @template TData of mixed
* @param class-string<TFormType> $type
* @param TData|null $data
* @param array<mixed> $options
* @return FormInterface<TData|null>
*/
protected function createFormWithName(string $name, string $type = FormType::class, mixed $data = null, array $options = []): FormInterface
{
return $this->container->get('form.factory')->createNamed($name, $type, $data, $options);
}
@@ -166,6 +189,9 @@ abstract class AbstractController extends BaseAbstractController implements Serv
/**
* Handles exception flash messages for failed update/create actions.
* @param \Exception $exception
* @param FormInterface $form
* @return void
*/
protected function handleFormUpdateException(\Exception $exception, FormInterface $form): void
{

View File

@@ -414,6 +414,10 @@ final class ActivityController extends AbstractController
return $writer->getFileResponse($spreadsheet);
}
/**
* @param ActivityQuery $query
* @return FormInterface<ActivityQuery>
*/
private function getToolbarForm(ActivityQuery $query): FormInterface
{
return $this->createSearchForm(ActivityToolbarForm::class, $query, [
@@ -423,6 +427,10 @@ final class ActivityController extends AbstractController
]);
}
/**
* @param Activity $activity
* @return FormInterface<ActivityEditForm>
*/
private function createEditForm(Activity $activity): FormInterface
{
$currency = $this->configuration->getCustomerDefaultCurrency();

View File

@@ -505,6 +505,10 @@ final class CustomerController extends AbstractController
]);
}
/**
* @param CustomerQuery $query
* @return FormInterface<CustomerQuery>
*/
private function getToolbarForm(CustomerQuery $query): FormInterface
{
return $this->createSearchForm(CustomerToolbarForm::class, $query, [
@@ -514,6 +518,10 @@ final class CustomerController extends AbstractController
]);
}
/**
* @param CustomerComment $comment
* @return FormInterface<CustomerComment>
*/
private function getCommentForm(CustomerComment $comment): FormInterface
{
if (null === $comment->getId()) {
@@ -526,6 +534,10 @@ final class CustomerController extends AbstractController
]);
}
/**
* @param Customer $customer
* @return FormInterface<Customer>
*/
private function createEditForm(Customer $customer): FormInterface
{
$event = new CustomerMetaDefinitionEvent($customer);

View File

@@ -157,6 +157,11 @@ final class ExportController extends AbstractController
return $this->export->getExportItems($query);
}
/**
* @param ExportQuery $query
* @param string $method
* @return FormInterface<ExportQuery>
*/
private function getToolbarForm(ExportQuery $query, string $method): FormInterface
{
return $this->createSearchForm(ExportToolbarForm::class, $query, [

View File

@@ -17,7 +17,7 @@ use App\Model\Statistic\StatisticDate;
use App\Repository\ActivityRepository;
use App\Repository\ProjectRepository;
use App\Timesheet\TimesheetStatisticService;
use DateTime;
use DateTimeInterface;
abstract class AbstractUserReportController extends AbstractController
{
@@ -35,17 +35,17 @@ abstract class AbstractUserReportController extends AbstractController
return true;
}
protected function getStatisticDataRaw(DateTime $begin, DateTime $end, User $user): array
protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
{
return $this->statisticService->getDailyStatisticsGrouped($begin, $end, [$user]);
}
protected function createStatisticModel(DateTime $begin, DateTime $end, User $user): DateStatisticInterface
protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface
{
return new DailyStatistic($begin, $end, $user);
}
protected function prepareReport(DateTime $begin, DateTime $end, User $user): array
protected function prepareReport(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
{
$data = $this->getStatisticDataRaw($begin, $end, $user);

View File

@@ -105,7 +105,9 @@ final class ReportUsersYearController extends AbstractController
$values->setDate(clone $defaultDate);
}
/** @var \DateTime $start */
$start = $values->getDate();
// there is a potential edge case bug for financial years:
// the last month will be skipped, if the financial year started on a different day than the first
$end = $dateTimeFactory->createEndOfFinancialYear($start);

View File

@@ -16,6 +16,7 @@ use App\Model\MonthlyStatistic;
use App\Reporting\YearByUser\YearByUser;
use App\Reporting\YearByUser\YearByUserForm;
use DateTime;
use DateTimeInterface;
use Exception;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -75,6 +76,7 @@ final class UserYearController extends AbstractUserReportController
$values->setDate(clone $defaultDate);
}
/** @var \DateTimeInterface $start */
$start = $values->getDate();
// there is a potential edge case bug for financial years:
// the last month will be skipped, if the financial year started on a different day than the first
@@ -82,10 +84,10 @@ final class UserYearController extends AbstractUserReportController
$selectedUser = $values->getUser();
$previous = clone $start;
$previous = DateTime::createFromInterface($start);
$previous->modify('-1 year');
$next = clone $start;
$next = DateTime::createFromInterface($start);
$next->modify('+1 year');
$data = $this->prepareReport($start, $end, $selectedUser);
@@ -105,12 +107,12 @@ final class UserYearController extends AbstractUserReportController
];
}
protected function getStatisticDataRaw(DateTime $begin, DateTime $end, User $user): array
protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array
{
return $this->statisticService->getMonthlyStatisticsGrouped($begin, $end, [$user]);
}
protected function createStatisticModel(DateTime $begin, DateTime $end, User $user): DateStatisticInterface
protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface
{
return new MonthlyStatistic($begin, $end, $user);
}