WIP: Adjust model, remove manager branch in navigation
This commit is contained in:
@@ -6,26 +6,25 @@ import { German } from 'flatpickr/dist/l10n/de';
|
|||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
|
|
||||||
static targets = [ 'field' ]
|
static targets = [ 'field' ]
|
||||||
static values = { format: String, minDate: String, maxDate: String, disableWeekends: Boolean }
|
static values = {
|
||||||
|
minDate: String,
|
||||||
|
maxDate: String,
|
||||||
|
disableWeekends: Boolean,
|
||||||
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
flatpickr.localize(German);
|
flatpickr.localize(German)
|
||||||
flatpickr.setDefaults({
|
|
||||||
dateFormat: 'd.m.Y',
|
|
||||||
allowInput: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
const dateFormat = this.formatValue || 'd.m.Y'
|
|
||||||
const minDate = this.minDateValue
|
const minDate = this.minDateValue
|
||||||
const maxDate = this.maxDateValue
|
const maxDate = this.maxDateValue
|
||||||
const options = {
|
const options = {
|
||||||
dateFormat: 'Y-m-d',
|
dateFormat: 'Y-m-d',
|
||||||
altInput: true,
|
altFormat: 'd.m.Y',
|
||||||
altFormat: dateFormat,
|
|
||||||
minDate,
|
minDate,
|
||||||
maxDate,
|
maxDate,
|
||||||
|
altInput: true,
|
||||||
allowInput: true,
|
allowInput: true,
|
||||||
onClose(dates, currentdatestring, instance) {
|
onClose(dates, currentdatestring, instance) {
|
||||||
instance.setDate(instance.altInput.value, true, instance.config.altFormat)
|
instance.setDate(instance.altInput.value, true, instance.config.altFormat)
|
||||||
|
|||||||
@@ -72,14 +72,6 @@ services:
|
|||||||
method: createTeamerMenu
|
method: createTeamerMenu
|
||||||
alias: admin_teamer
|
alias: admin_teamer
|
||||||
|
|
||||||
App\Menu\ManagerMenuBuilder:
|
|
||||||
arguments:
|
|
||||||
$factory: '@knp_menu.factory'
|
|
||||||
tags:
|
|
||||||
- name: knp_menu.menu_builder
|
|
||||||
method: createMainMenu
|
|
||||||
alias: manager_main
|
|
||||||
|
|
||||||
App\Menu\TeamerMenuBuilder:
|
App\Menu\TeamerMenuBuilder:
|
||||||
arguments:
|
arguments:
|
||||||
$factory: '@knp_menu.factory'
|
$factory: '@knp_menu.factory'
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20231007143035 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment CHANGE date_from date_from DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\', CHANGE date_to date_to DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\', CHANGE destination_bus_pro_id destination_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE assignment ADD CONSTRAINT FK_30C544BA816C6140 FOREIGN KEY (destination_id) REFERENCES bpn_date (id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_30C544BA816C6140 ON assignment (destination_id)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment DROP FOREIGN KEY FK_30C544BA816C6140');
|
||||||
|
$this->addSql('DROP INDEX IDX_30C544BA816C6140 ON assignment');
|
||||||
|
$this->addSql('ALTER TABLE assignment CHANGE date_from date_from DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', CHANGE date_to date_to DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', CHANGE destination_id destination_bus_pro_id INT DEFAULT NULL');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20231007144753 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment ADD pickup_date_and_time DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', DROP pickup_date');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment ADD pickup_date DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', DROP pickup_date_and_time');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20231007145904 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment ADD pickup_date DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\', DROP pickup_date_and_time');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment ADD pickup_date_and_time DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', DROP pickup_date');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20231007150056 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE TABLE job_profile_training (job_profile_id INT NOT NULL, training_id INT NOT NULL, INDEX IDX_F19E0BB8A68D82A5 (job_profile_id), INDEX IDX_F19E0BB8BEFD98D1 (training_id), PRIMARY KEY(job_profile_id, training_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||||
|
$this->addSql('ALTER TABLE job_profile_training ADD CONSTRAINT FK_F19E0BB8A68D82A5 FOREIGN KEY (job_profile_id) REFERENCES job_profile (id) ON DELETE CASCADE');
|
||||||
|
$this->addSql('ALTER TABLE job_profile_training ADD CONSTRAINT FK_F19E0BB8BEFD98D1 FOREIGN KEY (training_id) REFERENCES training (id) ON DELETE CASCADE');
|
||||||
|
$this->addSql('ALTER TABLE job_profile DROP FOREIGN KEY FK_1BB81D94FEBEF441');
|
||||||
|
$this->addSql('DROP INDEX IDX_1BB81D94FEBEF441 ON job_profile');
|
||||||
|
$this->addSql('ALTER TABLE job_profile DROP required_training_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE job_profile_training DROP FOREIGN KEY FK_F19E0BB8A68D82A5');
|
||||||
|
$this->addSql('ALTER TABLE job_profile_training DROP FOREIGN KEY FK_F19E0BB8BEFD98D1');
|
||||||
|
$this->addSql('DROP TABLE job_profile_training');
|
||||||
|
$this->addSql('ALTER TABLE job_profile ADD required_training_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE job_profile ADD CONSTRAINT FK_1BB81D94FEBEF441 FOREIGN KEY (required_training_id) REFERENCES training (id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_1BB81D94FEBEF441 ON job_profile (required_training_id)');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20231007151506 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment CHANGE pickup_date pickup_date DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE assignment CHANGE pickup_date pickup_date DATE NOT NULL COMMENT \'(DC2Type:date_immutable)\'');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,12 @@ namespace App\Controller\Admin\Application;
|
|||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
class IndexController extends AbstractController
|
class IndexController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/admin/application', name: 'app_admin_application_index')]
|
#[Route('/admin/application', name: 'app_admin_application_index')]
|
||||||
|
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
return $this->render('admin/application/index.html.twig');
|
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\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
class IndexController extends AbstractController
|
class IndexController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/admin/document', name: 'app_admin_document_index')]
|
#[Route('/admin/document', name: 'app_admin_document_index')]
|
||||||
|
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
return $this->render('admin/document/index.html.twig');
|
return $this->render('admin/document/index.html.twig');
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
|||||||
class IndexController extends AbstractController
|
class IndexController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/admin', name: 'app_admin_index')]
|
#[Route('/admin', name: 'app_admin_index')]
|
||||||
#[IsGranted('ROLE_ADMIN')]
|
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
return $this->render('admin/index.html.twig');
|
return $this->render('admin/index.html.twig');
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class IndexController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/admin/teamer', name: 'app_admin_teamer_index')]
|
#[Route('/admin/teamer', name: 'app_admin_teamer_index')]
|
||||||
#[IsGranted('ROLE_ADMIN')]
|
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||||
public function index(Request $request): Response
|
public function index(Request $request): Response
|
||||||
{
|
{
|
||||||
$query = $this
|
$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;
|
namespace App\Controller\Teamer\Profile;
|
||||||
|
|
||||||
|
use App\Entity\JobProfile;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use App\Form\TeamerJobProfileType;
|
use App\Form\TeamerJobProfileType;
|
||||||
use App\Repository\JobProfileRepository;
|
use App\Repository\JobProfileRepository;
|
||||||
@@ -34,15 +35,21 @@ class SkillsController extends AbstractController
|
|||||||
$selectableJobProfiles = [];
|
$selectableJobProfiles = [];
|
||||||
|
|
||||||
foreach ($jobProfiles as $profile) {
|
foreach ($jobProfiles as $profile) {
|
||||||
$selectableJobProfiles[$profile->getId()] = true;
|
/** @var JobProfile $profile */
|
||||||
if (null !== $profile->getRequiredTraining() && null === $teamer->getTrainingAttendance($profile->getRequiredTraining())) {
|
$jobProfileIsSelectable = false;
|
||||||
$selectableJobProfiles[$profile->getId()] = false;
|
foreach ($profile->getRequiredTrainings() as $training) {
|
||||||
}
|
if (null !== $teamer->getTrainingAttendance($training)) {
|
||||||
foreach ($profile->getRequiredLicenses() as $license) {
|
$jobProfileIsSelectable = true;
|
||||||
if (null === $teamer->getLicenseOfType($license)) {
|
break;
|
||||||
$selectableJobProfiles[$profile->getId()] = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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]);
|
$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 Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Uid\Uuid;
|
use Symfony\Component\Uid\Uuid;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: AssignmentRepository::class)]
|
#[ORM\Entity(repositoryClass: AssignmentRepository::class)]
|
||||||
class Assignment implements BlameableEntityInterface, TimestampableEntityInterface
|
class Assignment implements BlameableEntityInterface, TimestampableEntityInterface
|
||||||
@@ -39,17 +40,14 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
|||||||
#[Assert\Range(min: 1, minMessage: 'Die Mindestanzahl ist 1')]
|
#[Assert\Range(min: 1, minMessage: 'Die Mindestanzahl ist 1')]
|
||||||
private ?int $available = 1;
|
private ?int $available = 1;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||||
#[Assert\NotNull(message: 'Bitte gib das Beginndatum an')]
|
|
||||||
private ?\DateTimeImmutable $dateFrom = null;
|
private ?\DateTimeImmutable $dateFrom = null;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||||
#[Assert\NotNull(message: 'Bitte gib das Enddatum an')]
|
|
||||||
#[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Enddatum muss nach dem Beginndatum liegen')]
|
#[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Enddatum muss nach dem Beginndatum liegen')]
|
||||||
private ?\DateTimeImmutable $dateTo = null;
|
private ?\DateTimeImmutable $dateTo = null;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
|
||||||
#[Assert\GreaterThanOrEqual(propertyPath: 'dateFrom', message: 'Die Busabfahrt muss am oder nach dem Beginndatum liegen')]
|
|
||||||
private ?\DateTimeImmutable $pickupDate = null;
|
private ?\DateTimeImmutable $pickupDate = null;
|
||||||
|
|
||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ class BpnDate
|
|||||||
$this->bus = false;
|
$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
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
|
|||||||
+30
-15
@@ -5,6 +5,8 @@ namespace App\Entity;
|
|||||||
use App\Entity\Traits\BlameableEntity;
|
use App\Entity\Traits\BlameableEntity;
|
||||||
use App\Entity\Traits\TimestampableEntity;
|
use App\Entity\Traits\TimestampableEntity;
|
||||||
use App\Repository\JobProfileRepository;
|
use App\Repository\JobProfileRepository;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\DBAL\Types\Types;
|
use Doctrine\DBAL\Types\Types;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Uid\Uuid;
|
use Symfony\Component\Uid\Uuid;
|
||||||
@@ -28,15 +30,16 @@ class JobProfile implements BlameableEntityInterface, TimestampableEntityInterfa
|
|||||||
#[Assert\NotBlank(message: 'Bitte gib die Bezeichnung an')]
|
#[Assert\NotBlank(message: 'Bitte gib die Bezeichnung an')]
|
||||||
private ?string $name = null;
|
private ?string $name = null;
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
private ?Training $requiredTraining = null;
|
|
||||||
|
|
||||||
#[ORM\Column(type: Types::JSON)]
|
#[ORM\Column(type: Types::JSON)]
|
||||||
private array $requiredLicenses = [];
|
private array $requiredLicenses = [];
|
||||||
|
|
||||||
|
#[ORM\ManyToMany(targetEntity: Training::class)]
|
||||||
|
private Collection $requiredTrainings;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->uuid = Uuid::v4();
|
$this->uuid = Uuid::v4();
|
||||||
|
$this->requiredTrainings = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
@@ -61,18 +64,6 @@ class JobProfile implements BlameableEntityInterface, TimestampableEntityInterfa
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRequiredTraining(): ?Training
|
|
||||||
{
|
|
||||||
return $this->requiredTraining;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRequiredTraining(?Training $requiredTraining): static
|
|
||||||
{
|
|
||||||
$this->requiredTraining = $requiredTraining;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRequiredLicenses(): array
|
public function getRequiredLicenses(): array
|
||||||
{
|
{
|
||||||
return $this->requiredLicenses;
|
return $this->requiredLicenses;
|
||||||
@@ -84,4 +75,28 @@ class JobProfile implements BlameableEntityInterface, TimestampableEntityInterfa
|
|||||||
|
|
||||||
return $this;
|
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',
|
'label' => 'Destination',
|
||||||
'class' => BpnDate::class,
|
'class' => BpnDate::class,
|
||||||
'label_property' => 'product',
|
'label_property' => 'product',
|
||||||
|
'label_function' => function (BpnDate $date) {
|
||||||
|
return (string) $date;
|
||||||
|
},
|
||||||
'endpoint_route' => 'app_admin_autocomplete_bpndate',
|
'endpoint_route' => 'app_admin_autocomplete_bpndate',
|
||||||
])
|
])
|
||||||
->add('jobProfile', EntityType::class, [
|
->add('jobProfile', EntityType::class, [
|
||||||
@@ -39,10 +42,12 @@ class AssignmentType extends AbstractType
|
|||||||
'placeholder' => 'Bitte auswählen',
|
'placeholder' => 'Bitte auswählen',
|
||||||
])
|
])
|
||||||
->add('dateFrom', DatepickerType::class, [
|
->add('dateFrom', DatepickerType::class, [
|
||||||
'label' => 'Einsatztermin von',
|
'label' => 'abweichender Einsatztermin von',
|
||||||
|
'required' => false,
|
||||||
])
|
])
|
||||||
->add('dateTo', DatepickerType::class, [
|
->add('dateTo', DatepickerType::class, [
|
||||||
'label' => 'Einsatztermin bis',
|
'label' => 'abweichender Einsatztermin bis',
|
||||||
|
'required' => false,
|
||||||
])
|
])
|
||||||
->add('pickupDate', DatepickerType::class, [
|
->add('pickupDate', DatepickerType::class, [
|
||||||
'label' => 'Busabfahrt',
|
'label' => 'Busabfahrt',
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ class JobProfileType extends AbstractType
|
|||||||
->add('name', TextType::class, [
|
->add('name', TextType::class, [
|
||||||
'label' => 'Bezeichnung',
|
'label' => 'Bezeichnung',
|
||||||
])
|
])
|
||||||
->add('requiredTraining', EntityType::class, [
|
->add('requiredTrainings', EntityType::class, [
|
||||||
'label' => 'vorausgesetzte Fortbildung',
|
'label' => 'vorausgesetzte Fortbildung',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'placeholder' => 'keine',
|
'placeholder' => 'keine',
|
||||||
'class' => Training::class,
|
'class' => Training::class,
|
||||||
'choice_label' => 'name',
|
'choice_label' => 'name',
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
'query_builder' => function (EntityRepository $repository) {
|
'query_builder' => function (EntityRepository $repository) {
|
||||||
return $repository->createQueryBuilder('job_profile')
|
return $repository->createQueryBuilder('job_profile')
|
||||||
->orderBy('job_profile.name', 'ASC')
|
->orderBy('job_profile.name', 'ASC')
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Form;
|
|||||||
|
|
||||||
use App\Entity\JobProfile;
|
use App\Entity\JobProfile;
|
||||||
use App\Entity\Teamer;
|
use App\Entity\Teamer;
|
||||||
|
use App\Entity\Training;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
@@ -23,10 +24,11 @@ class TeamerJobProfileType extends AbstractType
|
|||||||
'class' => JobProfile::class,
|
'class' => JobProfile::class,
|
||||||
// Append potential training or license requirements to profile labels
|
// Append potential training or license requirements to profile labels
|
||||||
'choice_label' => function($choice, string $key, mixed $value): TranslatableMessage|string {
|
'choice_label' => function($choice, string $key, mixed $value): TranslatableMessage|string {
|
||||||
|
/** @var JobProfile $choice */
|
||||||
$label = $choice->getName();
|
$label = $choice->getName();
|
||||||
$requirements = [];
|
$requirements = [];
|
||||||
if (null !== $training = $choice->getRequiredTraining()) {
|
foreach ($choice->getRequiredTrainings() as $training) {
|
||||||
$requirements[].= $training->getName();
|
$requirements[] = $training->getName();
|
||||||
}
|
}
|
||||||
foreach ($choice->getRequiredLicenses() as $license) {
|
foreach ($choice->getRequiredLicenses() as $license) {
|
||||||
$requirements[] = sprintf('Offizielle %slehrer*innenlizenz', ucfirst(strtolower($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
|
protected function addTeamerItem(ItemInterface $menu): void
|
||||||
{
|
{
|
||||||
if ($this->security->isGranted('ROLE_TEAMER')) {
|
if ($this->security->isGranted('ROLE_TEAMER')) {
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
|||||||
|
|
||||||
$this->addDivider($menu);
|
$this->addDivider($menu);
|
||||||
|
|
||||||
$this->addManagerItem($menu);
|
|
||||||
$this->addTeamerItem($menu);
|
$this->addTeamerItem($menu);
|
||||||
|
|
||||||
$this->addDivider($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->addDivider($menu);
|
||||||
|
|
||||||
$this->addAdminItem($menu);
|
$this->addAdminItem($menu);
|
||||||
$this->addManagerItem($menu);
|
|
||||||
|
|
||||||
$this->addDivider($menu);
|
$this->addDivider($menu);
|
||||||
|
|
||||||
|
|||||||
@@ -29,17 +29,16 @@ class BpnDateRepository extends ServiceEntityRepository
|
|||||||
$qb = $this->createQueryBuilder('bpn_date');
|
$qb = $this->createQueryBuilder('bpn_date');
|
||||||
|
|
||||||
$dates = $qb
|
$dates = $qb
|
||||||
->select('bpn_date.id', 'bpn_date.product', 'bpn_date.hotel', 'bpn_date.dateFrom', 'bpn_date.dateTo')
|
|
||||||
->where($qb->expr()->orX(
|
->where($qb->expr()->orX(
|
||||||
$qb->expr()->like('bpn_date.product', ':product'),
|
$qb->expr()->like('bpn_date.product', ':product'),
|
||||||
$qb->expr()->like('bpn_date.hotel', ':hotel')
|
$qb->expr()->like('bpn_date.hotel', ':hotel')
|
||||||
))
|
))
|
||||||
->setParameter('product', '%'.$this->escapeLikeWildcards($search).'%')
|
->setParameter('product', '%'.$this->escapeLikeWildcards($search).'%')
|
||||||
->setParameter('hotel', '%'.$this->escapeLikeWildcards($search).'%')
|
->setParameter('hotel', '%'.$this->escapeLikeWildcards($search).'%')
|
||||||
->orderBy('bpn_date.product', 'ASC')
|
->orderBy('bpn_date.dateFrom', 'ASC')
|
||||||
->addOrderBy('bpn_date.dateFrom', 'ASC')
|
->addOrderBy('bpn_date.product', 'ASC')
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getArrayResult()
|
->getResult()
|
||||||
;
|
;
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
@@ -51,8 +50,8 @@ class BpnDateRepository extends ServiceEntityRepository
|
|||||||
|
|
||||||
foreach ($dates as $date) {
|
foreach ($dates as $date) {
|
||||||
$data[] = [
|
$data[] = [
|
||||||
'value' => $date['id'],
|
'value' => $date->getId(),
|
||||||
'text' => sprintf('%s (%s - %s)', $date['product'], $date['dateFrom']->format('d.m.y'), $date['dateTo']->format('d.m.y')),
|
'text' => (string) $date,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class JobProfileRepository extends ServiceEntityRepository
|
|||||||
|
|
||||||
return $qb
|
return $qb
|
||||||
->select('job_profile', 'required_training')
|
->select('job_profile', 'required_training')
|
||||||
->leftJoin('job_profile.requiredTraining', 'required_training')
|
->leftJoin('job_profile.requiredTrainings', 'required_training')
|
||||||
->orderBy('job_profile.name', 'ASC')
|
->orderBy('job_profile.name', 'ASC')
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult()
|
->getResult()
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
<div class="flex flex-col space-y-4 pb-8">
|
<div class="flex flex-col space-y-4 pb-8">
|
||||||
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
<div class="grid lg:grid-cols-4 gap-x-8 gap-y-4">
|
||||||
|
<div class="lg:col-span-3">
|
||||||
|
{{ form_row(form.destination) }}
|
||||||
|
</div>
|
||||||
{{ form_row(form.available) }}
|
{{ form_row(form.available) }}
|
||||||
{{ form_row(form.jobProfile) }}
|
|
||||||
</div>
|
|
||||||
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
|
||||||
{{ form_row(form.destination) }}
|
|
||||||
{{ form_row(form.contact) }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
||||||
{{ form_row(form.dateFrom) }}
|
{{ form_row(form.dateFrom) }}
|
||||||
{{ form_row(form.dateTo) }}
|
{{ form_row(form.dateTo) }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
||||||
|
{{ form_row(form.jobProfile) }}
|
||||||
|
{{ form_row(form.contact) }}
|
||||||
|
</div>
|
||||||
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
||||||
{{ form_row(form.pickupDate) }}
|
{{ form_row(form.pickupDate) }}
|
||||||
{{ form_row(form.pickup) }}
|
{{ form_row(form.pickup) }}
|
||||||
@@ -20,7 +22,9 @@
|
|||||||
{{ form_row(form.benefits) }}
|
{{ form_row(form.benefits) }}
|
||||||
{{ form_row(form.fees) }}
|
{{ form_row(form.fees) }}
|
||||||
</div>
|
</div>
|
||||||
{{ form_row(form.remarks) }}
|
<div class="grid lg:grid-cols-2 gap-x-8 gap-y-4">
|
||||||
|
{{ form_row(form.remarks) }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<button type="submit" class="btn">
|
<button type="submit" class="btn">
|
||||||
|
|||||||
@@ -21,14 +21,14 @@
|
|||||||
{{ knp_pagination_sortable(pagination, 'Jobprofil', 'assignment.jobProfile') }}
|
{{ knp_pagination_sortable(pagination, 'Jobprofil', 'assignment.jobProfile') }}
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
{{ knp_pagination_sortable(pagination, 'Destination', 'assignment.destinationBusProId') }}
|
{{ knp_pagination_sortable(pagination, 'Destination', 'destination.dateFrom') }}
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
{{ knp_pagination_sortable(pagination, 'Busabfahrt', 'assignment.pickupDate') }}
|
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
{{ knp_pagination_sortable(pagination, 'Busbegleitung ab', 'assignment.pickup') }}
|
{{ knp_pagination_sortable(pagination, 'Busbegleitung ab', 'assignment.pickup') }}
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Bewerbungen
|
||||||
|
</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -36,22 +36,28 @@
|
|||||||
{% for assignment in pagination %}
|
{% for assignment in pagination %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{{ assignment.dateFrom|date('d.m.Y') }}
|
{% set dateFrom = assignment.dateFrom ? assignment.dateFrom : assignment.destination.dateFrom %}
|
||||||
|
{{ dateFrom|date('d.m.Y') }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ assignment.dateTo|date('d.m.Y') }}
|
{% set dateTo = assignment.dateTo ? assignment.dateTo : assignment.destination.dateTo %}
|
||||||
|
{{ dateTo|date('d.m.Y') }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ assignment.jobProfile.name }}
|
{{ assignment.jobProfile.name }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ assignment.destinationBusProId|bpn_destination_label }}
|
{{ assignment.destination.product }}
|
||||||
|
<br>
|
||||||
|
{{ assignment.destination.hotel }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ assignment.pickupDate|date('d.m.Y') }}
|
{{ assignment.pickup ? assignment.pickup|bpn_pickup_label|default('-') : '-' }}
|
||||||
|
<br>
|
||||||
|
{{ assignment.pickupDate ? assignment.pickupDate|date('d.m.Y') : '' }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ assignment.pickup|bpn_pickup_label|default('-') }}
|
{{ assignment.applications|length }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="flex items-center space-x-1 justify-end">
|
<div class="flex items-center space-x-1 justify-end">
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
<div class="flex flex-col space-y-4 pb-8">
|
<div class="flex flex-col space-y-4 pb-8">
|
||||||
{{ form_row(form.name) }}
|
{{ form_row(form.name) }}
|
||||||
{{ form_row(form.requiredTraining) }}
|
{{ form_row(form.requiredTrainings) }}
|
||||||
{{ form_widget(form.requiredLicenses) }}
|
{{ form_row(form.requiredLicenses) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<button type="submit" class="btn">
|
<button type="submit" class="btn">
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
Bezeichnung
|
Bezeichnung
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Fortbildung
|
vorausg. Fortbildung(en)
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Lizenzen
|
vorausg. Lizenz(en)
|
||||||
</th>
|
</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -30,7 +30,17 @@
|
|||||||
{{ jobProfile.name }}
|
{{ jobProfile.name }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ jobProfile.requiredTraining.name|default('-') }}
|
<ul>
|
||||||
|
{% for training in jobProfile.requiredTrainings %}
|
||||||
|
<li>
|
||||||
|
{{ training.name }}
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
-
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user