WIP: Adjust model, remove manager branch in navigation
This commit is contained in:
@@ -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');
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,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)));
|
||||
|
||||
@@ -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')) {
|
||||
|
||||
@@ -125,7 +125,6 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
|
||||
$this->addDivider($menu);
|
||||
|
||||
$this->addManagerItem($menu);
|
||||
$this->addTeamerItem($menu);
|
||||
|
||||
$this->addDivider($menu);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,6 @@ class TeamerMenuBuilder extends AbstractMenuBuilder
|
||||
$this->addDivider($menu);
|
||||
|
||||
$this->addAdminItem($menu);
|
||||
$this->addManagerItem($menu);
|
||||
|
||||
$this->addDivider($menu);
|
||||
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user