monthly budget, monthly report, unified report calculation (#2684)
This commit is contained in:
@@ -124,6 +124,7 @@ final class ActivityController extends AbstractController
|
||||
$rates = [];
|
||||
$teams = null;
|
||||
$defaultTeam = null;
|
||||
$now = $this->getDateTimeFactory()->createDateTime();
|
||||
|
||||
if ($this->isGranted('edit', $activity)) {
|
||||
if ($this->isGranted('create_team')) {
|
||||
@@ -133,7 +134,7 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
|
||||
if ($this->isGranted('budget', $activity)) {
|
||||
$stats = $statisticService->getActivityStatistics($activity);
|
||||
$stats = $statisticService->getBudgetStatisticModel($activity, $now);
|
||||
}
|
||||
|
||||
if ($this->isGranted('permissions', $activity) || $this->isGranted('details', $activity) || $this->isGranted('view_team')) {
|
||||
@@ -146,7 +147,7 @@ final class ActivityController extends AbstractController
|
||||
'rates' => $rates,
|
||||
'team' => $defaultTeam,
|
||||
'teams' => $teams,
|
||||
'now' => $this->getDateTimeFactory()->createDateTime(),
|
||||
'now' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -283,6 +283,7 @@ final class CustomerController extends AbstractController
|
||||
$teams = null;
|
||||
$projects = null;
|
||||
$rates = [];
|
||||
$now = $this->getDateTimeFactory()->createDateTime();
|
||||
|
||||
if ($this->isGranted('edit', $customer)) {
|
||||
if ($this->isGranted('create_team')) {
|
||||
@@ -296,7 +297,7 @@ final class CustomerController extends AbstractController
|
||||
}
|
||||
|
||||
if ($this->isGranted('budget', $customer)) {
|
||||
$stats = $statisticService->getCustomerStatistics($customer);
|
||||
$stats = $statisticService->getBudgetStatisticModel($customer, $now);
|
||||
}
|
||||
|
||||
if ($this->isGranted('comments', $customer)) {
|
||||
@@ -321,7 +322,7 @@ final class CustomerController extends AbstractController
|
||||
'teams' => $teams,
|
||||
'customer_now' => new \DateTime('now', $timezone),
|
||||
'rates' => $rates,
|
||||
'now' => $this->getDateTimeFactory()->createDateTime(),
|
||||
'now' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ use App\Form\UserPreferencesForm;
|
||||
use App\Form\UserRolesType;
|
||||
use App\Form\UserTeamsType;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Timesheet\TimesheetStatisticService;
|
||||
use App\User\UserService;
|
||||
use App\Utils\LocaleSettings;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
@@ -48,20 +48,20 @@ final class ProfileController extends AbstractController
|
||||
* @Route(path="/{username}", name="user_profile", methods={"GET"})
|
||||
* @Security("is_granted('view', profile)")
|
||||
*/
|
||||
public function indexAction(User $profile, TimesheetRepository $repository, LocaleSettings $localeSettings): Response
|
||||
public function indexAction(User $profile, TimesheetRepository $repository, TimesheetStatisticService $statisticService): Response
|
||||
{
|
||||
$userStats = $repository->getUserStatistics($profile);
|
||||
$userStats = $repository->getUserStatistics($profile, false);
|
||||
$firstEntry = $statisticService->findFirstRecordDate($profile);
|
||||
|
||||
$begin = $userStats->getFirstEntry() ?? $this->getDateTimeFactory()->getStartOfMonth();
|
||||
$begin = $firstEntry ?? $this->getDateTimeFactory()->getStartOfMonth();
|
||||
$end = $this->getDateTimeFactory()->getEndOfMonth();
|
||||
$monthlyStats = $repository->getMonthlyStats($begin, $end, $profile);
|
||||
arsort($monthlyStats);
|
||||
|
||||
$viewVars = [
|
||||
'tab' => 'charts',
|
||||
'user' => $profile,
|
||||
'stats' => $userStats,
|
||||
'years' => $monthlyStats,
|
||||
'firstTimesheet' => $firstEntry,
|
||||
'workMonths' => $statisticService->getMonthlyStats($begin, $end, [$profile])[0]
|
||||
];
|
||||
|
||||
return $this->render('user/stats.html.twig', $viewVars);
|
||||
|
||||
@@ -304,6 +304,7 @@ final class ProjectController extends AbstractController
|
||||
$comments = null;
|
||||
$teams = null;
|
||||
$rates = [];
|
||||
$now = $this->getDateTimeFactory()->createDateTime();
|
||||
|
||||
if ($this->isGranted('edit', $project)) {
|
||||
if ($this->isGranted('create_team')) {
|
||||
@@ -313,7 +314,7 @@ final class ProjectController extends AbstractController
|
||||
}
|
||||
|
||||
if ($this->isGranted('budget', $project)) {
|
||||
$stats = $statisticService->getProjectStatistics($project);
|
||||
$stats = $statisticService->getBudgetStatisticModel($project, $now);
|
||||
}
|
||||
|
||||
if ($this->isGranted('comments', $project)) {
|
||||
@@ -337,7 +338,7 @@ final class ProjectController extends AbstractController
|
||||
'team' => $defaultTeam,
|
||||
'teams' => $teams,
|
||||
'rates' => $rates,
|
||||
'now' => $this->getDateTimeFactory()->createDateTime(),
|
||||
'now' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
60
src/Controller/Reporting/ProjectDateRangeController.php
Normal file
60
src/Controller/Reporting/ProjectDateRangeController.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?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\Controller\Reporting;
|
||||
|
||||
use App\Controller\AbstractController;
|
||||
use App\Form\Model\DateRange;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Reporting\ProjectDateRange\ProjectDateRangeForm;
|
||||
use App\Reporting\ProjectDateRange\ProjectDateRangeQuery;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
final class ProjectDateRangeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route(path="/reporting/project_daterange", name="report_project_daterange", methods={"GET","POST"})
|
||||
* @Security("is_granted('view_reporting') and is_granted('budget_project')")
|
||||
*/
|
||||
public function __invoke(Request $request, ProjectStatisticService $service)
|
||||
{
|
||||
$dateFactory = $this->getDateTimeFactory();
|
||||
$user = $this->getUser();
|
||||
|
||||
$query = new ProjectDaterangeQuery($dateFactory->getStartOfMonth(), $user);
|
||||
$form = $this->createForm(ProjectDateRangeForm::class, $query, [
|
||||
'timezone' => $user->getTimezone()
|
||||
]);
|
||||
$form->submit($request->query->all(), false);
|
||||
|
||||
$dateRange = new DateRange(true);
|
||||
$dateRange->setBegin($query->getMonth());
|
||||
$dateRange->setEnd($dateFactory->getEndOfMonth($dateRange->getBegin()));
|
||||
|
||||
$projects = $service->findProjectsForDateRange($query, $dateRange);
|
||||
$entries = $service->getBudgetStatisticModelForProjectsByDateRange($projects, $dateRange->getBegin(), $dateRange->getEnd(), $dateRange->getEnd());
|
||||
|
||||
$byCustomer = [];
|
||||
foreach ($entries as $entry) {
|
||||
$customer = $entry->getProject()->getCustomer();
|
||||
if (!isset($byCustomer[$customer->getId()])) {
|
||||
$byCustomer[$customer->getId()] = ['customer' => $customer, 'projects' => []];
|
||||
}
|
||||
$byCustomer[$customer->getId()]['projects'][] = $entry;
|
||||
}
|
||||
|
||||
return $this->render('reporting/project_daterange.html.twig', [
|
||||
'entries' => $byCustomer,
|
||||
'form' => $form->createView(),
|
||||
'queryEnd' => $dateRange->getEnd(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ final class ProjectDetailsController extends AbstractController
|
||||
}
|
||||
|
||||
return $this->render('reporting/project_details.html.twig', [
|
||||
'project' => $query->getProject(),
|
||||
'project_view' => $projectView,
|
||||
'project_details' => $projectDetails,
|
||||
'form' => $form->createView(),
|
||||
|
||||
@@ -17,7 +17,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
final class InactiveProjectController extends AbstractController
|
||||
final class ProjectInactiveController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route(path="/reporting/project_inactive", name="report_project_inactive", methods={"GET","POST"})
|
||||
@@ -27,6 +27,7 @@ final class InactiveProjectController extends AbstractController
|
||||
{
|
||||
$dateFactory = $this->getDateTimeFactory();
|
||||
$user = $this->getUser();
|
||||
$now = $dateFactory->createDateTime();
|
||||
|
||||
$query = new ProjectInactiveQuery($dateFactory->createDateTime('-1 year'), $user);
|
||||
$form = $this->createForm(ProjectInactiveForm::class, $query, [
|
||||
@@ -35,7 +36,7 @@ final class InactiveProjectController extends AbstractController
|
||||
$form->submit($request->query->all(), false);
|
||||
|
||||
$projects = $service->findInactiveProjects($query);
|
||||
$entries = $service->getProjectView($user, $projects, $query->getLastChange());
|
||||
$entries = $service->getProjectView($user, $projects, $now);
|
||||
|
||||
$byCustomer = [];
|
||||
foreach ($entries as $entry) {
|
||||
@@ -51,7 +52,8 @@ final class InactiveProjectController extends AbstractController
|
||||
'form' => $form->createView(),
|
||||
'title' => 'report_inactive_project',
|
||||
'tableName' => 'inactive_project_reporting',
|
||||
'now' => $this->getDateTimeFactory()->createDateTime(),
|
||||
'now' => $now,
|
||||
'skipColumns' => ['today', 'week', 'month', 'projectStart', 'projectEnd', 'comment'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -49,8 +49,7 @@ final class ProjectViewController extends AbstractController
|
||||
'form' => $form->createView(),
|
||||
'title' => 'report_project_view',
|
||||
'tableName' => 'project_view_reporting',
|
||||
'now' => $this->getDateTimeFactory()->createDateTime(),
|
||||
'showDurations' => true,
|
||||
'now' => $dateFactory->createDateTime(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,18 @@
|
||||
namespace App\Controller\Reporting;
|
||||
|
||||
use App\Controller\AbstractController;
|
||||
use App\Model\Statistic\Day;
|
||||
use App\Entity\User;
|
||||
use App\Model\DailyStatistic;
|
||||
use App\Model\Statistic\StatisticDate;
|
||||
use App\Reporting\MonthByUser;
|
||||
use App\Reporting\MonthByUserForm;
|
||||
use App\Reporting\WeekByUser;
|
||||
use App\Reporting\WeekByUserForm;
|
||||
use App\Repository\ActivityRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Timesheet\TimesheetStatisticService;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -29,14 +35,17 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
*/
|
||||
final class ReportByUserController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @var TimesheetRepository
|
||||
*/
|
||||
private $timesheetRepository;
|
||||
private $statisticService;
|
||||
private $projectRepository;
|
||||
private $activityRepository;
|
||||
|
||||
public function __construct(TimesheetRepository $timesheetRepository)
|
||||
public function __construct(TimesheetRepository $timesheetRepository, TimesheetStatisticService $statisticService, ProjectRepository $projectRepository, ActivityRepository $activityRepository)
|
||||
{
|
||||
$this->timesheetRepository = $timesheetRepository;
|
||||
$this->statisticService = $statisticService;
|
||||
$this->projectRepository = $projectRepository;
|
||||
$this->activityRepository = $activityRepository;
|
||||
}
|
||||
|
||||
private function canSelectUser(): bool
|
||||
@@ -60,7 +69,6 @@ final class ReportByUserController extends AbstractController
|
||||
{
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory($currentUser);
|
||||
$localeFormats = $this->getLocaleFormats($request->getLocale());
|
||||
$canChangeUser = $this->canSelectUser();
|
||||
|
||||
$values = new MonthByUser();
|
||||
@@ -71,7 +79,6 @@ final class ReportByUserController extends AbstractController
|
||||
'include_user' => $canChangeUser,
|
||||
'timezone' => $dateTimeFactory->getTimezone()->getName(),
|
||||
'start_date' => $values->getDate(),
|
||||
'format' => $localeFormats->getDateTypeFormat(),
|
||||
]);
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
@@ -102,15 +109,14 @@ final class ReportByUserController extends AbstractController
|
||||
$nextMonth = clone $start;
|
||||
$nextMonth->modify('+1 month');
|
||||
|
||||
$data = $this->timesheetRepository->getDailyStats($selectedUser, $start, $end);
|
||||
$rows = $this->prepareReportData($data);
|
||||
$data = $this->prepareReport($start, $end, $selectedUser);
|
||||
|
||||
return $this->render('reporting/report_by_user.html.twig', [
|
||||
'report_title' => 'report_user_month',
|
||||
'box_id' => 'user-month-reporting-box',
|
||||
'form' => $form->createView(),
|
||||
'days' => $data,
|
||||
'rows' => $rows,
|
||||
'rows' => $data,
|
||||
'days' => new DailyStatistic($start, $end, $selectedUser),
|
||||
'user' => $selectedUser,
|
||||
'current' => $start,
|
||||
'next' => $nextMonth,
|
||||
@@ -129,7 +135,6 @@ final class ReportByUserController extends AbstractController
|
||||
{
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory($currentUser);
|
||||
$localeFormats = $this->getLocaleFormats($request->getLocale());
|
||||
$canChangeUser = $this->canSelectUser();
|
||||
|
||||
$values = new WeekByUser();
|
||||
@@ -140,7 +145,6 @@ final class ReportByUserController extends AbstractController
|
||||
'include_user' => $canChangeUser,
|
||||
'timezone' => $dateTimeFactory->getTimezone()->getName(),
|
||||
'start_date' => $values->getDate(),
|
||||
'format' => $localeFormats->getDateTypeFormat(),
|
||||
]);
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
@@ -159,7 +163,6 @@ final class ReportByUserController extends AbstractController
|
||||
|
||||
$start = $dateTimeFactory->getStartOfWeek($values->getDate());
|
||||
$end = $dateTimeFactory->getEndOfWeek($values->getDate());
|
||||
|
||||
$selectedUser = $values->getUser();
|
||||
|
||||
$previous = clone $start;
|
||||
@@ -168,15 +171,14 @@ final class ReportByUserController extends AbstractController
|
||||
$next = clone $start;
|
||||
$next->modify('+1 week');
|
||||
|
||||
$data = $this->timesheetRepository->getDailyStats($selectedUser, $start, $end);
|
||||
$rows = $this->prepareReportData($data);
|
||||
$data = $this->prepareReport($start, $end, $selectedUser);
|
||||
|
||||
return $this->render('reporting/report_by_user.html.twig', [
|
||||
'report_title' => 'report_user_week',
|
||||
'box_id' => 'user-week-reporting-box',
|
||||
'form' => $form->createView(),
|
||||
'days' => $data,
|
||||
'rows' => $rows,
|
||||
'days' => new DailyStatistic($start, $end, $selectedUser),
|
||||
'rows' => $data,
|
||||
'user' => $selectedUser,
|
||||
'current' => $start,
|
||||
'next' => $next,
|
||||
@@ -184,50 +186,52 @@ final class ReportByUserController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Day[] $data
|
||||
* @return array
|
||||
*/
|
||||
private function prepareReportData(array $data): array
|
||||
private function prepareReport(DateTime $begin, DateTime $end, User $user): array
|
||||
{
|
||||
$days = [];
|
||||
$data = $this->statisticService->getDailyStatisticsGrouped($begin, $end, [$user]);
|
||||
|
||||
foreach ($data as $day) {
|
||||
$days[$day->getDay()->format('Ymd')] = ['date' => $day->getDay(), 'duration' => 0];
|
||||
$data = array_pop($data);
|
||||
$projectIds = [];
|
||||
$activityIds = [];
|
||||
|
||||
foreach ($data as $projectId => $projectValues) {
|
||||
$projectIds[$projectId] = $projectId;
|
||||
$dailyProjectStatistic = new DailyStatistic($begin, $end, $user);
|
||||
foreach ($projectValues['activities'] as $activityId => $activityValues) {
|
||||
$activityIds[$activityId] = $activityId;
|
||||
if (!isset($data[$projectId]['duration'])) {
|
||||
$data[$projectId]['duration'] = 0;
|
||||
}
|
||||
if (!isset($data[$projectId]['activities'][$activityId]['duration'])) {
|
||||
$data[$projectId]['activities'][$activityId]['duration'] = 0;
|
||||
}
|
||||
/** @var StatisticDate $day */
|
||||
foreach ($activityValues['days']->getDays() as $day) {
|
||||
$statDay = $dailyProjectStatistic->getDayByDateTime($day->getDate());
|
||||
$statDay->setTotalDuration($statDay->getTotalDuration() + $day->getDuration());
|
||||
$data[$projectId]['duration'] = $data[$projectId]['duration'] + $day->getDuration();
|
||||
$data[$projectId]['activities'][$activityId]['duration'] = $data[$projectId]['activities'][$activityId]['duration'] + $day->getDuration();
|
||||
}
|
||||
}
|
||||
$data[$projectId]['days'] = $dailyProjectStatistic;
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
$activities = $this->activityRepository->findByIds($activityIds);
|
||||
foreach ($activities as $activity) {
|
||||
$activityIds[$activity->getId()] = $activity;
|
||||
}
|
||||
|
||||
foreach ($data as $day) {
|
||||
$dayId = $day->getDay()->format('Ymd');
|
||||
foreach ($day->getDetails() as $id => $detail) {
|
||||
$projectId = $detail['project']->getId();
|
||||
if (!\array_key_exists($projectId, $rows)) {
|
||||
$rows[$projectId] = [
|
||||
'project' => $detail['project'],
|
||||
'duration' => 0,
|
||||
'days' => $days,
|
||||
'activities' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$rows[$projectId]['duration'] += $detail['duration'];
|
||||
$rows[$projectId]['days'][$dayId]['duration'] += $detail['duration'];
|
||||
|
||||
$activityId = $detail['activity']->getId();
|
||||
if (!\array_key_exists($activityId, $rows[$projectId]['activities'])) {
|
||||
$rows[$projectId]['activities'][$activityId] = [
|
||||
'activity' => $detail['activity'],
|
||||
'duration' => 0,
|
||||
'days' => $days,
|
||||
];
|
||||
}
|
||||
|
||||
$rows[$projectId]['activities'][$activityId]['duration'] += $detail['duration'];
|
||||
$rows[$projectId]['activities'][$activityId]['days'][$dayId]['duration'] += $detail['duration'];
|
||||
foreach ($data as $projectId => $projectValues) {
|
||||
foreach ($projectValues['activities'] as $activityId => $activityValues) {
|
||||
$data[$projectId]['activities'][$activityId]['activity'] = $activityIds[$activityId];
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
$projects = $this->projectRepository->findByIds($projectIds);
|
||||
foreach ($projects as $project) {
|
||||
$data[$project->getId()]['project'] = $project;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace App\Controller\Reporting;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Controller\AbstractController;
|
||||
use App\Model\Statistic\Day;
|
||||
use App\Model\Statistic\Year;
|
||||
use App\Model\DailyStatistic;
|
||||
use App\Model\MonthlyStatistic;
|
||||
use App\Reporting\MonthlyUserList;
|
||||
use App\Reporting\MonthlyUserListForm;
|
||||
use App\Reporting\WeeklyUserList;
|
||||
@@ -22,6 +22,7 @@ use App\Reporting\YearlyUserListForm;
|
||||
use App\Repository\Query\UserQuery;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Timesheet\TimesheetStatisticService;
|
||||
use Exception;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -34,13 +35,7 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||
*/
|
||||
final class ReportUsersListController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @var TimesheetRepository
|
||||
*/
|
||||
private $timesheetRepository;
|
||||
/**
|
||||
* @var UserRepository
|
||||
*/
|
||||
private $userRepository;
|
||||
|
||||
public function __construct(TimesheetRepository $timesheetRepository, UserRepository $userRepository)
|
||||
@@ -56,11 +51,10 @@ final class ReportUsersListController extends AbstractController
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function yearlyUsersList(Request $request, SystemConfiguration $systemConfiguration): Response
|
||||
public function yearlyUsersList(Request $request, SystemConfiguration $systemConfiguration, TimesheetStatisticService $statisticService): Response
|
||||
{
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory();
|
||||
$localeFormats = $this->getLocaleFormats($request->getLocale());
|
||||
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
@@ -71,15 +65,12 @@ final class ReportUsersListController extends AbstractController
|
||||
$defaultDate = $this->getDateTimeFactory()->createStartOfFinancialYear($financialYear);
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
|
||||
$values = new YearlyUserList();
|
||||
$values->setDate(clone $defaultDate);
|
||||
|
||||
$form = $this->createForm(YearlyUserListForm::class, $values, [
|
||||
'timezone' => $dateTimeFactory->getTimezone()->getName(),
|
||||
'start_date' => $values->getDate(),
|
||||
'format' => $localeFormats->getDateTypeFormat(),
|
||||
]);
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
@@ -93,123 +84,49 @@ final class ReportUsersListController extends AbstractController
|
||||
}
|
||||
|
||||
$start = $values->getDate();
|
||||
$end = $this->getDateTimeFactory()->createEndOfFinancialYear($start);
|
||||
// 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);
|
||||
|
||||
$months = [];
|
||||
$totals = [];
|
||||
foreach ($allUsers as $user) {
|
||||
$rows[] = [
|
||||
'years' => $this->timesheetRepository->getMonthlyStats($start, $end, $user),
|
||||
'user' => $user
|
||||
];
|
||||
$monthStats = [];
|
||||
$hasData = true;
|
||||
|
||||
if (!empty($allUsers)) {
|
||||
$monthStats = $statisticService->getMonthlyStats($start, $end, $allUsers);
|
||||
}
|
||||
|
||||
if (isset($rows[0])) {
|
||||
/** @var Year $year */
|
||||
foreach ($rows[0]['years'] as $year) {
|
||||
foreach ($year->getMonths() as $month) {
|
||||
$date = new \DateTime();
|
||||
$date->setDate((int) $year->getYear(), $month->getMonthNumber(), 1);
|
||||
$date->setTime(0, 0, 0);
|
||||
$months[$date->format('Ym')] = $date;
|
||||
}
|
||||
}
|
||||
foreach ($rows as $row) {
|
||||
foreach ($row['years'] as $year) {
|
||||
foreach ($year->getMonths() as $month) {
|
||||
$date = new \DateTime();
|
||||
$date->setDate((int) $year->getYear(), $month->getMonthNumber(), 1);
|
||||
$totalsId = $date->format('Ym');
|
||||
if (!isset($totals[$totalsId])) {
|
||||
$totals[$totalsId] = 0;
|
||||
}
|
||||
$totals[$totalsId] += $month->getTotalDuration();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($monthStats)) {
|
||||
$monthStats = [new MonthlyStatistic($start, $end, $currentUser)];
|
||||
$hasData = false;
|
||||
}
|
||||
/*
|
||||
foreach ($allUsers as $user) {
|
||||
$rows[] = [
|
||||
'days' => $this->timesheetRepository->getDailyStats($user, $start, $end),
|
||||
'user' => $user
|
||||
];
|
||||
}
|
||||
|
||||
$userYears = [];
|
||||
|
||||
if (isset($rows[0])) {
|
||||
foreach ($rows[0]['days'] as $day) {
|
||||
$months[$day->getDay()->format('Ym')] = $day->getDay();
|
||||
}
|
||||
foreach ($rows as $row) {
|
||||
$userYear = ['user' => $row['user']];
|
||||
foreach ($row['days'] as $day) {
|
||||
$yearId = $day->getDay()->format('Y');
|
||||
$monthId = $day->getDay()->format('m');
|
||||
$totalsId = $yearId.$monthId;
|
||||
|
||||
if (!array_key_exists('years', $userYear)) {
|
||||
$userYear['years'] = [];
|
||||
}
|
||||
if (!array_key_exists($yearId, $userYear['years'])) {
|
||||
$userYear['years'][$yearId] = ['year' => $yearId];
|
||||
}
|
||||
if (!array_key_exists('months', $userYear['years'][$yearId])) {
|
||||
$userYear['years'][$yearId]['months'] = [];
|
||||
}
|
||||
if (!array_key_exists($monthId, $userYear['years'][$yearId]['months'])) {
|
||||
$userYear['years'][$yearId]['months'][$monthId] = ['month' => $monthId, 'totalDuration' => 0];
|
||||
}
|
||||
if (!array_key_exists($totalsId, $totals)) {
|
||||
$totals[$totalsId] = 0;
|
||||
}
|
||||
|
||||
$totals[$totalsId] += $day->getTotalDuration();
|
||||
$userYear['years'][$yearId]['months'][$monthId]['totalDuration'] += $day->getTotalDuration();;
|
||||
}
|
||||
$userYears[] = $userYear;
|
||||
}
|
||||
}
|
||||
$rows = $userYears;
|
||||
*/
|
||||
|
||||
return $this->render('reporting/report_user_list_monthly.html.twig', [
|
||||
'report_title' => 'report_yearly_users',
|
||||
'box_id' => 'yearly-user-list-reporting-box',
|
||||
'form' => $form->createView(),
|
||||
'rows' => $rows,
|
||||
'months' => $months,
|
||||
'totals' => $totals,
|
||||
'stats' => $monthStats,
|
||||
'hasData' => $hasData,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route(path="/monthly_users_list", name="report_monthly_users", methods={"GET","POST"})
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function monthlyUsersList(Request $request): Response
|
||||
public function monthlyUsersList(Request $request, TimesheetStatisticService $statisticService): Response
|
||||
{
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory();
|
||||
$localeFormats = $this->getLocaleFormats($request->getLocale());
|
||||
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
$allUsers = $this->userRepository->getUsersForQuery($query);
|
||||
|
||||
$rows = [];
|
||||
|
||||
$values = new MonthlyUserList();
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
|
||||
$form = $this->createForm(MonthlyUserListForm::class, $values, [
|
||||
'timezone' => $dateTimeFactory->getTimezone()->getName(),
|
||||
'start_date' => $values->getDate(),
|
||||
'format' => $localeFormats->getDateTypeFormat(),
|
||||
]);
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
@@ -234,71 +151,50 @@ final class ReportUsersListController extends AbstractController
|
||||
$next = clone $start;
|
||||
$next->modify('+1 month');
|
||||
|
||||
foreach ($allUsers as $user) {
|
||||
$rows[] = [
|
||||
'days' => $this->timesheetRepository->getDailyStats($user, $start, $end),
|
||||
'user' => $user
|
||||
];
|
||||
$dayStats = [];
|
||||
$hasData = true;
|
||||
|
||||
if (!empty($allUsers)) {
|
||||
$dayStats = $statisticService->getDailyStatistics($start, $end, $allUsers);
|
||||
}
|
||||
|
||||
$days = [];
|
||||
$totals = [];
|
||||
|
||||
if (isset($rows[0])) {
|
||||
/** @var Day $day */
|
||||
foreach ($rows[0]['days'] as $day) {
|
||||
$days[$day->getDay()->format('Ymd')] = $day->getDay();
|
||||
}
|
||||
foreach ($rows as $row) {
|
||||
foreach ($row['days'] as $day) {
|
||||
$totalsId = $day->getDay()->format('Ymd');
|
||||
if (!isset($totals[$totalsId])) {
|
||||
$totals[$totalsId] = 0;
|
||||
}
|
||||
$totals[$totalsId] += $day->getTotalDuration();
|
||||
}
|
||||
}
|
||||
if (empty($dayStats)) {
|
||||
$dayStats = [new DailyStatistic($start, $end, $currentUser)];
|
||||
$hasData = false;
|
||||
}
|
||||
|
||||
return $this->render('reporting/report_user_list.html.twig', [
|
||||
'report_title' => 'report_monthly_users',
|
||||
'box_id' => 'monthly-user-list-reporting-box',
|
||||
'form' => $form->createView(),
|
||||
'rows' => $rows,
|
||||
'days' => $days,
|
||||
'totals' => $totals,
|
||||
'current' => $start,
|
||||
'next' => $next,
|
||||
'previous' => $previous,
|
||||
'subReportDate' => $values->getDate(),
|
||||
'subReportRoute' => 'report_user_month',
|
||||
'stats' => $dayStats,
|
||||
'hasData' => $hasData,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route(path="/weekly_users_list", name="report_weekly_users", methods={"GET","POST"})
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function weeklyUsersList(Request $request): Response
|
||||
public function weeklyUsersList(Request $request, TimesheetStatisticService $statisticService): Response
|
||||
{
|
||||
$currentUser = $this->getUser();
|
||||
$dateTimeFactory = $this->getDateTimeFactory();
|
||||
$localeFormats = $this->getLocaleFormats($request->getLocale());
|
||||
|
||||
$query = new UserQuery();
|
||||
$query->setCurrentUser($currentUser);
|
||||
$allUsers = $this->userRepository->getUsersForQuery($query);
|
||||
|
||||
$rows = [];
|
||||
|
||||
$values = new WeeklyUserList();
|
||||
$values->setDate($dateTimeFactory->getStartOfWeek());
|
||||
|
||||
$form = $this->createForm(WeeklyUserListForm::class, $values, [
|
||||
'timezone' => $dateTimeFactory->getTimezone()->getName(),
|
||||
'start_date' => $values->getDate(),
|
||||
'format' => $localeFormats->getDateTypeFormat(),
|
||||
]);
|
||||
|
||||
$form->submit($request->query->all(), false);
|
||||
@@ -320,42 +216,29 @@ final class ReportUsersListController extends AbstractController
|
||||
$next = clone $start;
|
||||
$next->modify('+1 week');
|
||||
|
||||
foreach ($allUsers as $user) {
|
||||
$rows[] = [
|
||||
'days' => $this->timesheetRepository->getDailyStats($user, $start, $end),
|
||||
'user' => $user
|
||||
];
|
||||
$dayStats = [];
|
||||
$hasData = true;
|
||||
|
||||
if (!empty($allUsers)) {
|
||||
$dayStats = $statisticService->getDailyStatistics($start, $end, $allUsers);
|
||||
}
|
||||
|
||||
$days = [];
|
||||
$totals = [];
|
||||
|
||||
if (isset($rows[0])) {
|
||||
/** @var Day $day */
|
||||
foreach ($rows[0]['days'] as $day) {
|
||||
$days[$day->getDay()->format('Ymd')] = $day->getDay();
|
||||
}
|
||||
foreach ($rows as $row) {
|
||||
foreach ($row['days'] as $day) {
|
||||
$totalsId = $day->getDay()->format('Ymd');
|
||||
if (!isset($totals[$totalsId])) {
|
||||
$totals[$totalsId] = 0;
|
||||
}
|
||||
$totals[$totalsId] += $day->getTotalDuration();
|
||||
}
|
||||
}
|
||||
if (empty($dayStats)) {
|
||||
$dayStats = [new DailyStatistic($start, $end, $currentUser)];
|
||||
$hasData = false;
|
||||
}
|
||||
|
||||
return $this->render('reporting/report_user_list.html.twig', [
|
||||
'report_title' => 'report_weekly_users',
|
||||
'box_id' => 'weekly-user-list-reporting-box',
|
||||
'form' => $form->createView(),
|
||||
'rows' => $rows,
|
||||
'days' => $days,
|
||||
'totals' => $totals,
|
||||
'current' => $start,
|
||||
'next' => $next,
|
||||
'previous' => $previous,
|
||||
'subReportDate' => $values->getDate(),
|
||||
'subReportRoute' => 'report_user_week',
|
||||
'stats' => $dayStats,
|
||||
'hasData' => $hasData,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user