diff --git a/src/Controller/Administrative/Assignment/TimelineController.php b/src/Controller/Administrative/Assignment/TimelineController.php index 485b27a..f6bbb6e 100644 --- a/src/Controller/Administrative/Assignment/TimelineController.php +++ b/src/Controller/Administrative/Assignment/TimelineController.php @@ -2,10 +2,12 @@ namespace App\Controller\Administrative\Assignment; +use App\Entity\User; use App\Repository\AssignmentRepository; use App\Service\Assignment\TimelineService; use App\Service\Common\TimelineFilterHandler; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; @@ -20,17 +22,26 @@ class TimelineController extends AbstractController } #[Route('/administrative/timeline', name: 'app_administrative_timeline')] - #[IsGranted('ROLE_ADMINISTRATIVE')] + #[IsGranted(new Expression('is_granted("ROLE_ADMINISTRATIVE") or is_granted("ROLE_HOUSE_MANAGER")'))] public function index(): Response { + /** @var User $user */ + $user = $this->getUser(); + $period = $this->timelineService->getActiveWindow(); $this->filterHandler->setPeriod($period); $filterDto = $this->filterHandler->getFilterSettings(); + $hotelCodes = null; + if ($this->isGranted('ROLE_HOUSE_MANAGER')) { + $filterDto->setHotels([]); + $hotelCodes = $user->getHotelCodes(); + } + $assignments = $this ->assignmentRepository - ->getListQuery($filterDto, 'destination.dateFrom') + ->getListQuery($filterDto, 'destination.dateFrom', $hotelCodes) ->getResult() ; $timelineData = $this->timelineService->preprocess($assignments); diff --git a/src/Controller/Common/TimelineFilterController.php b/src/Controller/Common/TimelineFilterController.php index 65093b3..021deae 100644 --- a/src/Controller/Common/TimelineFilterController.php +++ b/src/Controller/Common/TimelineFilterController.php @@ -8,6 +8,7 @@ use App\Htmx\HxRedirectResponse; use App\Service\Assignment\TimelineService; use App\Service\Common\TimelineFilterHandler; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; @@ -26,10 +27,13 @@ class TimelineFilterController extends AbstractController } #[Route('/common/timeline/filter', name: 'app_common_timeline_filter')] - #[IsGranted('ROLE_ADMINISTRATIVE')] + #[IsGranted(new Expression('is_granted("ROLE_ADMINISTRATIVE") or is_granted("ROLE_HOUSE_MANAGER")'))] public function index(Request $request): Response { $formData = $this->filterHandler->getFilterSettings(); + if ($this->isGranted('ROLE_HOUSE_MANAGER')) { + $formData->setHotels([]); + } $form = $this->createForm(TimelineFilterType::class, $formData); $form->handleRequest($request); diff --git a/src/Form/TimelineFilterType.php b/src/Form/TimelineFilterType.php index 688e3ef..8d932e0 100644 --- a/src/Form/TimelineFilterType.php +++ b/src/Form/TimelineFilterType.php @@ -4,6 +4,7 @@ namespace App\Form; use App\Model\TimelineFilterDto; use App\Service\Assignment\TimelineService; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\FormBuilderInterface; @@ -13,6 +14,7 @@ class TimelineFilterType extends AbstractType { public function __construct( private readonly TimelineService $timelineService, + private readonly Security $security, private readonly array $destinations, ) { } @@ -50,21 +52,23 @@ class TimelineFilterType extends AbstractType ]) ; - $destinations = $this->destinations; - $hotelChoices = []; - sort($destinations); - foreach ($destinations as $item) { - $hotelChoices[$item] = $item; - } + if (false === $this->security->isGranted('ROLE_HOUSE_MANAGER')) { + $destinations = $this->destinations; + $hotelChoices = []; + sort($destinations); + foreach ($destinations as $item) { + $hotelChoices[$item] = $item; + } - $builder - ->add('hotels', MultiselectType::class, [ - 'label' => 'Haus/Destination', - 'required' => false, - 'empty_label' => 'nicht filtern', - 'choices' => $hotelChoices, - ]) - ; + $builder + ->add('hotels', MultiselectType::class, [ + 'label' => 'Haus/Destination', + 'required' => false, + 'empty_label' => 'nicht filtern', + 'choices' => $hotelChoices, + ]) + ; + } } public function configureOptions(OptionsResolver $resolver): void diff --git a/src/Menu/HouseManagerMenuBuilder.php b/src/Menu/HouseManagerMenuBuilder.php index 977b040..1c5cfe7 100644 --- a/src/Menu/HouseManagerMenuBuilder.php +++ b/src/Menu/HouseManagerMenuBuilder.php @@ -31,6 +31,15 @@ class HouseManagerMenuBuilder extends AbstractMenuBuilder ], ], ]); + $menu->addChild('Zeitleiste', [ + 'route' => 'app_administrative_timeline', + 'linkAttributes' => [ + 'title' => 'Zeitleiste', + ], + 'extras' => [ + 'icon' => 'table', + ], + ]); $this->addAdminItem($menu); $this->addManagerItem($menu); diff --git a/src/Repository/AssignmentRepository.php b/src/Repository/AssignmentRepository.php index 8aa5270..9a3e55f 100644 --- a/src/Repository/AssignmentRepository.php +++ b/src/Repository/AssignmentRepository.php @@ -32,7 +32,7 @@ class AssignmentRepository extends ServiceEntityRepository parent::__construct($registry, Assignment::class); } - public function getListQuery(AssignmentFilterDto $filterDto, ?string $orderBy = null): Query + public function getListQuery(AssignmentFilterDto $filterDto, ?string $orderBy = null, ?array $hotelCodes = null): Query { $qb = $this->createQueryBuilder('assignment'); @@ -56,6 +56,7 @@ class AssignmentRepository extends ServiceEntityRepository } $this->applyFilterSettings($filterDto, $qb); + $this->applyHotelCodeRestriction($qb, $hotelCodes); return $qb->getQuery(); } @@ -231,6 +232,27 @@ class AssignmentRepository extends ServiceEntityRepository } } + private function applyHotelCodeRestriction(QueryBuilder $qb, ?array $hotelCodes = null): void + { + if (null === $hotelCodes) { + return; + } + + if ([] === $hotelCodes) { + $qb->andWhere('1 = 0'); + + return; + } + + $qb + ->andWhere($qb->expr()->orX( + $qb->expr()->in($qb->expr()->substring('destination.hotelCode', 1, 3), ':hotelCodes'), + $qb->expr()->in($qb->expr()->substring('destination.hotelCode', -3, 3), ':hotelCodes'), + )) + ->setParameter('hotelCodes', $hotelCodes) + ; + } + public function getBookmarkQueryForTeamer(Teamer $teamer): Query { // Find ids of assignments with available slots first diff --git a/templates/administrative/assignment/timeline.html.twig b/templates/administrative/assignment/timeline.html.twig index 19bc3c0..4bbed51 100644 --- a/templates/administrative/assignment/timeline.html.twig +++ b/templates/administrative/assignment/timeline.html.twig @@ -11,10 +11,14 @@ }) }}" colspan="{{ colspan }}"> {% if item.type == 'disposition' %}
- - {{ item.jobProfile }} - + {% if is_granted('ROLE_HOUSE_MANAGER') %} + {{ item.jobProfile }} + {% else %} + + {{ item.jobProfile }} + + {% endif %} |
{% else %} - - {{ item.jobProfile }} - + {% if is_granted('ROLE_HOUSE_MANAGER') %} + {{ item.jobProfile }} + {% else %} + + {{ item.jobProfile }} + + {% endif %} {% endif %} {% endmacro %} diff --git a/templates/common/modal_timeline_filter.html.twig b/templates/common/modal_timeline_filter.html.twig index d3bc2b8..deb519b 100644 --- a/templates/common/modal_timeline_filter.html.twig +++ b/templates/common/modal_timeline_filter.html.twig @@ -9,7 +9,9 @@ {{ form_row(filterForm.dateFrom) }} {{ form_row(filterForm.dateTo) }} - {{ form_row(filterForm.hotels) }} + {% if filterForm.hotels is defined %} + {{ form_row(filterForm.hotels) }} + {% endif %}
{{ form_widget(filterForm.apply, { 'attr': { 'class': 'btn' } }) }} {{ form_widget(filterForm.reset, { 'attr': { 'class': 'btn btn--secondary' } }) }}