WIP: Adjust model, remove manager branch in navigation

This commit is contained in:
Björn Fromme
2023-10-07 17:34:40 +02:00
parent 25a90b04aa
commit 8740041e7a
30 changed files with 302 additions and 152 deletions
@@ -5,10 +5,12 @@ namespace App\Controller\Admin\Application;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class IndexController extends AbstractController
{
#[Route('/admin/application', name: 'app_admin_application_index')]
#[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(): Response
{
return $this->render('admin/application/index.html.twig');
@@ -5,10 +5,12 @@ namespace App\Controller\Admin\Document;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class IndexController extends AbstractController
{
#[Route('/admin/document', name: 'app_admin_document_index')]
#[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(): Response
{
return $this->render('admin/document/index.html.twig');
+1 -1
View File
@@ -10,7 +10,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
class IndexController extends AbstractController
{
#[Route('/admin', name: 'app_admin_index')]
#[IsGranted('ROLE_ADMIN')]
#[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(): Response
{
return $this->render('admin/index.html.twig');
@@ -19,7 +19,7 @@ class IndexController extends AbstractController
}
#[Route('/admin/teamer', name: 'app_admin_teamer_index')]
#[IsGranted('ROLE_ADMIN')]
#[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Request $request): Response
{
$query = $this
@@ -1,19 +0,0 @@
<?php
namespace App\Controller\Common\Assignment;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class CreateController extends AbstractController
{
#[Route('/assignment/create', name: 'app_common_assignment_create')]
#[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Request $request): Response
{
}
}
@@ -1,18 +0,0 @@
<?php
namespace App\Controller\Manager;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class IndexController extends AbstractController
{
#[Route('/manager', name: 'app_manager_index')]
#[IsGranted('ROLE_MANAGER')]
public function index(): Response
{
return $this->render('manager/index.html.twig');
}
}
@@ -2,6 +2,7 @@
namespace App\Controller\Teamer\Profile;
use App\Entity\JobProfile;
use App\Entity\User;
use App\Form\TeamerJobProfileType;
use App\Repository\JobProfileRepository;
@@ -34,15 +35,21 @@ class SkillsController extends AbstractController
$selectableJobProfiles = [];
foreach ($jobProfiles as $profile) {
$selectableJobProfiles[$profile->getId()] = true;
if (null !== $profile->getRequiredTraining() && null === $teamer->getTrainingAttendance($profile->getRequiredTraining())) {
$selectableJobProfiles[$profile->getId()] = false;
}
foreach ($profile->getRequiredLicenses() as $license) {
if (null === $teamer->getLicenseOfType($license)) {
$selectableJobProfiles[$profile->getId()] = false;
/** @var JobProfile $profile */
$jobProfileIsSelectable = false;
foreach ($profile->getRequiredTrainings() as $training) {
if (null !== $teamer->getTrainingAttendance($training)) {
$jobProfileIsSelectable = true;
break;
}
}
foreach ($profile->getRequiredLicenses() as $license) {
if (null !== $teamer->getLicenseOfType($license)) {
$jobProfileIsSelectable = true;
break;
}
}
$selectableJobProfiles[$profile->getId()] = $jobProfileIsSelectable;
}
$form = $this->createForm(TeamerJobProfileType::class, $teamer, ['job_profiles' => $jobProfiles, 'selectable_job_profiles' => $selectableJobProfiles]);
+4 -6
View File
@@ -12,6 +12,7 @@ use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Entity(repositoryClass: AssignmentRepository::class)]
class Assignment implements BlameableEntityInterface, TimestampableEntityInterface
@@ -39,17 +40,14 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
#[Assert\Range(min: 1, minMessage: 'Die Mindestanzahl ist 1')]
private ?int $available = 1;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
#[Assert\NotNull(message: 'Bitte gib das Beginndatum an')]
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $dateFrom = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
#[Assert\NotNull(message: 'Bitte gib das Enddatum an')]
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
#[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Enddatum muss nach dem Beginndatum liegen')]
private ?\DateTimeImmutable $dateTo = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
#[Assert\GreaterThanOrEqual(propertyPath: 'dateFrom', message: 'Die Busabfahrt muss am oder nach dem Beginndatum liegen')]
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $pickupDate = null;
#[ORM\Column(nullable: true)]
+10
View File
@@ -49,6 +49,16 @@ class BpnDate
$this->bus = false;
}
public function __toString(): string
{
return sprintf('%s - %s: %s, %s',
$this->getDateFrom()->format('d.m.y'),
$this->getDateTo()->format('d.m.y'),
$this->getProduct(),
$this->getHotel()
);
}
public function getId(): ?int
{
return $this->id;
+30 -15
View File
@@ -5,6 +5,8 @@ namespace App\Entity;
use App\Entity\Traits\BlameableEntity;
use App\Entity\Traits\TimestampableEntity;
use App\Repository\JobProfileRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;
@@ -28,15 +30,16 @@ class JobProfile implements BlameableEntityInterface, TimestampableEntityInterfa
#[Assert\NotBlank(message: 'Bitte gib die Bezeichnung an')]
private ?string $name = null;
#[ORM\ManyToOne]
private ?Training $requiredTraining = null;
#[ORM\Column(type: Types::JSON)]
private array $requiredLicenses = [];
#[ORM\ManyToMany(targetEntity: Training::class)]
private Collection $requiredTrainings;
public function __construct()
{
$this->uuid = Uuid::v4();
$this->requiredTrainings = new ArrayCollection();
}
public function getId(): ?int
@@ -61,18 +64,6 @@ class JobProfile implements BlameableEntityInterface, TimestampableEntityInterfa
return $this;
}
public function getRequiredTraining(): ?Training
{
return $this->requiredTraining;
}
public function setRequiredTraining(?Training $requiredTraining): static
{
$this->requiredTraining = $requiredTraining;
return $this;
}
public function getRequiredLicenses(): array
{
return $this->requiredLicenses;
@@ -84,4 +75,28 @@ class JobProfile implements BlameableEntityInterface, TimestampableEntityInterfa
return $this;
}
/**
* @return Collection<int, Training>
*/
public function getRequiredTrainings(): Collection
{
return $this->requiredTrainings;
}
public function addRequiredTraining(Training $requiredTraining): static
{
if (!$this->requiredTrainings->contains($requiredTraining)) {
$this->requiredTrainings->add($requiredTraining);
}
return $this;
}
public function removeRequiredTraining(Training $requiredTraining): static
{
$this->requiredTrainings->removeElement($requiredTraining);
return $this;
}
}
+7 -2
View File
@@ -30,6 +30,9 @@ class AssignmentType extends AbstractType
'label' => 'Destination',
'class' => BpnDate::class,
'label_property' => 'product',
'label_function' => function (BpnDate $date) {
return (string) $date;
},
'endpoint_route' => 'app_admin_autocomplete_bpndate',
])
->add('jobProfile', EntityType::class, [
@@ -39,10 +42,12 @@ class AssignmentType extends AbstractType
'placeholder' => 'Bitte auswählen',
])
->add('dateFrom', DatepickerType::class, [
'label' => 'Einsatztermin von',
'label' => 'abweichender Einsatztermin von',
'required' => false,
])
->add('dateTo', DatepickerType::class, [
'label' => 'Einsatztermin bis',
'label' => 'abweichender Einsatztermin bis',
'required' => false,
])
->add('pickupDate', DatepickerType::class, [
'label' => 'Busabfahrt',
+3 -1
View File
@@ -21,12 +21,14 @@ class JobProfileType extends AbstractType
->add('name', TextType::class, [
'label' => 'Bezeichnung',
])
->add('requiredTraining', EntityType::class, [
->add('requiredTrainings', EntityType::class, [
'label' => 'vorausgesetzte Fortbildung',
'required' => false,
'placeholder' => 'keine',
'class' => Training::class,
'choice_label' => 'name',
'multiple' => true,
'expanded' => true,
'query_builder' => function (EntityRepository $repository) {
return $repository->createQueryBuilder('job_profile')
->orderBy('job_profile.name', 'ASC')
+4 -2
View File
@@ -4,6 +4,7 @@ namespace App\Form;
use App\Entity\JobProfile;
use App\Entity\Teamer;
use App\Entity\Training;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
@@ -23,10 +24,11 @@ class TeamerJobProfileType extends AbstractType
'class' => JobProfile::class,
// Append potential training or license requirements to profile labels
'choice_label' => function($choice, string $key, mixed $value): TranslatableMessage|string {
/** @var JobProfile $choice */
$label = $choice->getName();
$requirements = [];
if (null !== $training = $choice->getRequiredTraining()) {
$requirements[].= $training->getName();
foreach ($choice->getRequiredTrainings() as $training) {
$requirements[] = $training->getName();
}
foreach ($choice->getRequiredLicenses() as $license) {
$requirements[] = sprintf('Offizielle %slehrer*innenlizenz', ucfirst(strtolower($license)));
-11
View File
@@ -88,17 +88,6 @@ abstract class AbstractMenuBuilder
}
}
protected function addManagerItem(ItemInterface $menu): void
{
if ($this->security->isGranted('ROLE_MANAGER')) {
$menu
->addChild('Managerbereich', ['route' => 'app_manager_index'])
->setChildrenAttribute('title', 'Managerbereich')
->setExtra('icon', 'user')
;
}
}
protected function addTeamerItem(ItemInterface $menu): void
{
if ($this->security->isGranted('ROLE_TEAMER')) {
-1
View File
@@ -125,7 +125,6 @@ class AdminMenuBuilder extends AbstractMenuBuilder
$this->addDivider($menu);
$this->addManagerItem($menu);
$this->addTeamerItem($menu);
$this->addDivider($menu);
-22
View File
@@ -1,22 +0,0 @@
<?php
namespace App\Menu;
use Knp\Menu\ItemInterface;
class ManagerMenuBuilder extends AbstractMenuBuilder
{
public function createMainMenu(array $options): ItemInterface
{
$menu = $this->createRootElement();
$this->addAdminItem($menu);
$this->addTeamerItem($menu);
$this->addDivider($menu);
$this->addLogoutItem($menu);
return $menu;
}
}
-1
View File
@@ -86,7 +86,6 @@ class TeamerMenuBuilder extends AbstractMenuBuilder
$this->addDivider($menu);
$this->addAdminItem($menu);
$this->addManagerItem($menu);
$this->addDivider($menu);
+5 -6
View File
@@ -29,17 +29,16 @@ class BpnDateRepository extends ServiceEntityRepository
$qb = $this->createQueryBuilder('bpn_date');
$dates = $qb
->select('bpn_date.id', 'bpn_date.product', 'bpn_date.hotel', 'bpn_date.dateFrom', 'bpn_date.dateTo')
->where($qb->expr()->orX(
$qb->expr()->like('bpn_date.product', ':product'),
$qb->expr()->like('bpn_date.hotel', ':hotel')
))
->setParameter('product', '%'.$this->escapeLikeWildcards($search).'%')
->setParameter('hotel', '%'.$this->escapeLikeWildcards($search).'%')
->orderBy('bpn_date.product', 'ASC')
->addOrderBy('bpn_date.dateFrom', 'ASC')
->orderBy('bpn_date.dateFrom', 'ASC')
->addOrderBy('bpn_date.product', 'ASC')
->getQuery()
->getArrayResult()
->getResult()
;
$data = [
@@ -51,8 +50,8 @@ class BpnDateRepository extends ServiceEntityRepository
foreach ($dates as $date) {
$data[] = [
'value' => $date['id'],
'text' => sprintf('%s (%s - %s)', $date['product'], $date['dateFrom']->format('d.m.y'), $date['dateTo']->format('d.m.y')),
'value' => $date->getId(),
'text' => (string) $date,
];
}
+1 -1
View File
@@ -27,7 +27,7 @@ class JobProfileRepository extends ServiceEntityRepository
return $qb
->select('job_profile', 'required_training')
->leftJoin('job_profile.requiredTraining', 'required_training')
->leftJoin('job_profile.requiredTrainings', 'required_training')
->orderBy('job_profile.name', 'ASC')
->getQuery()
->getResult()