diff --git a/migrations/Version20231020145208.php b/migrations/Version20231020145208.php new file mode 100644 index 0000000..690e7be --- /dev/null +++ b/migrations/Version20231020145208.php @@ -0,0 +1,49 @@ +addSql('ALTER TABLE assignment ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE availability ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE destination ADD created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', ADD updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE disposition ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE fee ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE job_profile ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE training ADD deleted_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + } + + public function postUp(Schema $schema): void + { + $timestamp = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); + $this->connection->executeQuery('UPDATE destination set created_at=?', [$timestamp]); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE disposition DROP deleted_at'); + $this->addSql('ALTER TABLE assignment DROP deleted_at'); + $this->addSql('ALTER TABLE destination DROP created_at, DROP updated_at, DROP deleted_at'); + $this->addSql('ALTER TABLE job_profile DROP deleted_at'); + $this->addSql('ALTER TABLE training DROP deleted_at'); + $this->addSql('ALTER TABLE fee DROP deleted_at'); + $this->addSql('ALTER TABLE availability DROP deleted_at'); + } +} diff --git a/src/Command/BpnImportCommand.php b/src/Command/BpnImportCommand.php index 450855c..f550060 100644 --- a/src/Command/BpnImportCommand.php +++ b/src/Command/BpnImportCommand.php @@ -94,6 +94,7 @@ class BpnImportCommand extends Command 'product' => $product, 'pickups' => json_encode($datePickups), 'country' => $hotel->getCountry(), + 'updated_at' => (new \DateTimeImmutable())->format('Y-m-d H:i:s') ], [ 'id' => $id, 'hotel_bus_pro_id' => $hotelBusProId, @@ -114,6 +115,7 @@ class BpnImportCommand extends Command 'hotel_bus_pro_id' => $hotelBusProId, 'pickups' => json_encode($datePickups), 'country' => $hotel->getCountry(), + 'created_at' => (new \DateTimeImmutable())->format('Y-m-d H:i:s') ]) ; ++$addedCount; diff --git a/src/Controller/Admin/Assignment/DeleteController.php b/src/Controller/Admin/Assignment/DeleteController.php new file mode 100644 index 0000000..7a267d7 --- /dev/null +++ b/src/Controller/Admin/Assignment/DeleteController.php @@ -0,0 +1,36 @@ +setDeleted(); + $this->entityManager->flush(); + + $this->logger->info('Delete assignment', [ + 'assignment' => $assignment->getUuid(), + ]); + + $this->addFlash('success', 'Der Einsatz wurde gelöscht'); + + return $this->redirectToRoute('app_admin_assignment_index'); + } +} \ No newline at end of file diff --git a/src/Controller/Admin/System/Availability/DeleteController.php b/src/Controller/Admin/System/Availability/DeleteController.php index 74cb284..ea3a826 100644 --- a/src/Controller/Admin/System/Availability/DeleteController.php +++ b/src/Controller/Admin/System/Availability/DeleteController.php @@ -22,7 +22,7 @@ class DeleteController extends AbstractController #[IsGranted('ROLE_ADMIN')] public function index(Availability $availability): Response { - $this->entityManager->remove($availability); + $availability->setDeleted(); $this->entityManager->flush(); $this->addFlash('success', 'Die Verfügbarkeit wurde gelöscht'); diff --git a/src/Controller/Admin/System/Fee/DeleteController.php b/src/Controller/Admin/System/Fee/DeleteController.php index 4c2af23..5516540 100644 --- a/src/Controller/Admin/System/Fee/DeleteController.php +++ b/src/Controller/Admin/System/Fee/DeleteController.php @@ -22,7 +22,7 @@ class DeleteController extends AbstractController #[IsGranted('ROLE_ADMIN')] public function index(Fee $fee): Response { - $this->entityManager->remove($fee); + $fee->setDeleted(); $this->entityManager->flush(); $this->addFlash('success', 'Das Honorar wurde gelöscht'); diff --git a/src/Controller/Admin/System/Fee/IndexController.php b/src/Controller/Admin/System/Fee/IndexController.php index 48ead6c..f600aa3 100644 --- a/src/Controller/Admin/System/Fee/IndexController.php +++ b/src/Controller/Admin/System/Fee/IndexController.php @@ -17,7 +17,7 @@ class IndexController extends AbstractController #[IsGranted('ROLE_ADMIN')] public function index(): Response { - $fees = $this->feeRepository->findBy([], ['name' => 'ASC']); + $fees = $this->feeRepository->getList(); return $this->render('admin/system/fee/index.html.twig', [ 'fees' => $fees, diff --git a/src/Controller/Admin/System/JobProfile/DeleteController.php b/src/Controller/Admin/System/JobProfile/DeleteController.php index fd6ce93..a238a9e 100644 --- a/src/Controller/Admin/System/JobProfile/DeleteController.php +++ b/src/Controller/Admin/System/JobProfile/DeleteController.php @@ -22,7 +22,7 @@ class DeleteController extends AbstractController #[IsGranted('ROLE_ADMIN')] public function index(JobProfile $jobProfile): Response { - $this->entityManager->remove($jobProfile); + $jobProfile->setDeleted(); $this->entityManager->flush(); $this->addFlash('success', 'Das Job-Profil wurde gelöscht'); diff --git a/src/Controller/Admin/System/Training/DeleteController.php b/src/Controller/Admin/System/Training/DeleteController.php index 14b3871..a9c4b8d 100644 --- a/src/Controller/Admin/System/Training/DeleteController.php +++ b/src/Controller/Admin/System/Training/DeleteController.php @@ -22,7 +22,7 @@ class DeleteController extends AbstractController #[IsGranted('ROLE_ADMIN')] public function index(Training $training): Response { - $this->entityManager->remove($training); + $training->setDeleted(); $this->entityManager->flush(); $this->addFlash('success', 'Die Fortbildung wurde gelöscht'); diff --git a/src/Entity/Assignment.php b/src/Entity/Assignment.php index a1f2d26..5d443c4 100644 --- a/src/Entity/Assignment.php +++ b/src/Entity/Assignment.php @@ -3,6 +3,7 @@ namespace App\Entity; use App\Entity\Traits\BlameableEntity; +use App\Entity\Traits\SoftDeletableEntity; use App\Entity\Traits\TimestampableEntity; use App\Repository\AssignmentRepository; use Carbon\CarbonPeriod; @@ -14,10 +15,11 @@ use Symfony\Component\Uid\Uuid; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: AssignmentRepository::class)] -class Assignment implements BlameableEntityInterface, TimestampableEntityInterface +class Assignment implements BlameableEntityInterface, TimestampableEntityInterface, SoftDeletableEntityInterface { use BlameableEntity; use TimestampableEntity; + use SoftDeletableEntity; #[ORM\Id] #[ORM\GeneratedValue] diff --git a/src/Entity/Availability.php b/src/Entity/Availability.php index 53ca2d9..0c8bed7 100644 --- a/src/Entity/Availability.php +++ b/src/Entity/Availability.php @@ -3,6 +3,7 @@ namespace App\Entity; use App\Entity\Traits\BlameableEntity; +use App\Entity\Traits\SoftDeletableEntity; use App\Entity\Traits\TimestampableEntity; use App\Repository\AvailabilityRepository; use Doctrine\Common\Collections\ArrayCollection; @@ -12,10 +13,11 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: AvailabilityRepository::class)] -class Availability implements BlameableEntityInterface, TimestampableEntityInterface +class Availability implements BlameableEntityInterface, TimestampableEntityInterface, SoftDeletableEntityInterface { use BlameableEntity; use TimestampableEntity; + use SoftDeletableEntity; #[ORM\Id] #[ORM\GeneratedValue] diff --git a/src/Entity/Destination.php b/src/Entity/Destination.php index f226a2b..0948df0 100644 --- a/src/Entity/Destination.php +++ b/src/Entity/Destination.php @@ -2,13 +2,18 @@ namespace App\Entity; +use App\Entity\Traits\SoftDeletableEntity; +use App\Entity\Traits\TimestampableEntity; use App\Repository\DestinationRepository; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: DestinationRepository::class)] -class Destination +class Destination implements TimestampableEntityInterface, SoftDeletableEntityInterface { + use TimestampableEntity; + use SoftDeletableEntity; + #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] diff --git a/src/Entity/Disposition.php b/src/Entity/Disposition.php index de56ed0..744d001 100644 --- a/src/Entity/Disposition.php +++ b/src/Entity/Disposition.php @@ -3,6 +3,7 @@ namespace App\Entity; use App\Entity\Traits\BlameableEntity; +use App\Entity\Traits\SoftDeletableEntity; use App\Entity\Traits\TimestampableEntity; use App\Repository\DispositionRepository; use Doctrine\Common\Collections\ArrayCollection; @@ -12,10 +13,11 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Uid\Uuid; #[ORM\Entity(repositoryClass: DispositionRepository::class)] -class Disposition implements BlameableEntityInterface, TimestampableEntityInterface +class Disposition implements BlameableEntityInterface, TimestampableEntityInterface, SoftDeletableEntityInterface { use BlameableEntity; use TimestampableEntity; + use SoftDeletableEntity; public const STATUS_NEW = 'new'; public const STATUS_CHECKING_CONTRACT = 'checking_contract'; diff --git a/src/Entity/Fee.php b/src/Entity/Fee.php index 6bbabdb..618c09a 100644 --- a/src/Entity/Fee.php +++ b/src/Entity/Fee.php @@ -3,16 +3,18 @@ namespace App\Entity; use App\Entity\Traits\BlameableEntity; +use App\Entity\Traits\SoftDeletableEntity; use App\Entity\Traits\TimestampableEntity; use App\Repository\FeeRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: FeeRepository::class)] -class Fee implements BlameableEntityInterface, TimestampableEntityInterface +class Fee implements BlameableEntityInterface, TimestampableEntityInterface, SoftDeletableEntityInterface { use BlameableEntity; use TimestampableEntity; + use SoftDeletableEntity; #[ORM\Id] #[ORM\GeneratedValue] diff --git a/src/Entity/JobProfile.php b/src/Entity/JobProfile.php index f1002a7..402080c 100644 --- a/src/Entity/JobProfile.php +++ b/src/Entity/JobProfile.php @@ -3,6 +3,7 @@ namespace App\Entity; use App\Entity\Traits\BlameableEntity; +use App\Entity\Traits\SoftDeletableEntity; use App\Entity\Traits\TimestampableEntity; use App\Repository\JobProfileRepository; use Doctrine\Common\Collections\ArrayCollection; @@ -13,10 +14,11 @@ use Symfony\Component\Uid\Uuid; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: JobProfileRepository::class)] -class JobProfile implements BlameableEntityInterface, TimestampableEntityInterface +class JobProfile implements BlameableEntityInterface, TimestampableEntityInterface, SoftDeletableEntityInterface { use BlameableEntity; use TimestampableEntity; + use SoftDeletableEntity; #[ORM\Id] #[ORM\GeneratedValue] diff --git a/src/Entity/SoftDeletableEntityInterface.php b/src/Entity/SoftDeletableEntityInterface.php new file mode 100644 index 0000000..86a82dc --- /dev/null +++ b/src/Entity/SoftDeletableEntityInterface.php @@ -0,0 +1,10 @@ +deletedAt; + } + + public function setDeletedAt(\DateTimeImmutable $deletedAt): static + { + $this->deletedAt = $deletedAt; + + return $this; + } + + public function setDeleted(): static + { + $this->setDeletedAt(new \DateTimeImmutable()); + + return $this; + } + + public function isDeleted(): bool + { + return null !== $this->getDeletedAt(); + } +} diff --git a/src/Form/AssignmentType.php b/src/Form/AssignmentType.php index 87618d8..4a4a09f 100644 --- a/src/Form/AssignmentType.php +++ b/src/Form/AssignmentType.php @@ -78,6 +78,10 @@ class AssignmentType extends AbstractType return $fee->getName(); }, + 'query_builder' => function (EntityRepository $repository) { + $qb = $repository->createQueryBuilder('fee'); + return $qb->where($qb->expr()->isNull('fee.deletedAt')); + }, 'multiple' => true, 'expanded' => true, ]) diff --git a/src/Form/TeamerJobProfileType.php b/src/Form/TeamerJobProfileType.php index 182584c..66def3f 100644 --- a/src/Form/TeamerJobProfileType.php +++ b/src/Form/TeamerJobProfileType.php @@ -5,6 +5,7 @@ namespace App\Form; use App\Entity\JobProfile; use App\Entity\Teamer; use App\Entity\Training; +use Doctrine\ORM\EntityRepository; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -49,6 +50,10 @@ class TeamerJobProfileType extends AbstractType return ['disabled' => 'disabled']; }, + 'query_builder' => function (EntityRepository $repository) { + $qb = $repository->createQueryBuilder('job_profile'); + return $qb->where($qb->expr()->isNull('job_profile.deletedAt')); + }, 'expanded' => true, 'multiple' => true, ]) diff --git a/src/Repository/AssignmentRepository.php b/src/Repository/AssignmentRepository.php index ef2eeda..4244686 100644 --- a/src/Repository/AssignmentRepository.php +++ b/src/Repository/AssignmentRepository.php @@ -32,6 +32,7 @@ class AssignmentRepository extends ServiceEntityRepository ->select('assignment', 'destination', 'job_profile', 'application', 'disposition') ->innerJoin('assignment.destination', 'destination') ->innerJoin('assignment.jobProfile', 'job_profile') + ->where($qb->expr()->isNull('assignment.deletedAt')) ; if (null !== $teamer) { @@ -61,6 +62,7 @@ class AssignmentRepository extends ServiceEntityRepository ->innerJoin('assignment.teamers', 'teamer', Join::WITH, 'teamer = :teamer') ->leftJoin('assignment.applications', 'application', Join::WITH, 'application.teamer = :teamer') ->leftJoin('assignment.dispositions', 'disposition', Join::WITH, 'disposition.teamer = :teamer') + ->where($qb->expr()->isNull('assignment.deletedAt')) ->setParameter('teamer', $teamer) ; @@ -76,6 +78,7 @@ class AssignmentRepository extends ServiceEntityRepository $result = $qb ->select('MIN(destination.dateFrom) minDate', 'MAX(destination.dateTo) maxDate') ->innerJoin('assignment.destination', 'destination') + ->where($qb->expr()->isNull('assignment.deletedAt')) ->getQuery() ->getSingleResult() ; @@ -89,6 +92,7 @@ class AssignmentRepository extends ServiceEntityRepository ->select('job_profile.id', 'job_profile.name') ->innerJoin('assignment.jobProfile', 'job_profile') ->orderBy('job_profile.name', 'ASC') + ->where($qb->expr()->isNull('assignment.deletedAt')) ->getQuery() ->getArrayResult() ; @@ -102,6 +106,7 @@ class AssignmentRepository extends ServiceEntityRepository $result = $qb ->select('destination.id id', 'destination.product product', 'destination.hotel hotel') ->innerJoin('assignment.destination', 'destination') + ->where($qb->expr()->isNull('assignment.deletedAt')) ->orderBy('destination.product', 'ASC') ->groupBy('destination.id') ->getQuery() diff --git a/src/Repository/AvailabilityRepository.php b/src/Repository/AvailabilityRepository.php index f12918e..d133400 100644 --- a/src/Repository/AvailabilityRepository.php +++ b/src/Repository/AvailabilityRepository.php @@ -30,7 +30,8 @@ class AvailabilityRepository extends ServiceEntityRepository return $qb ->where($qb->expr()->andX( $qb->expr()->gt('availability.dateFrom', ':today'), - $qb->expr()->isNull('availability.owner') + $qb->expr()->isNull('availability.owner'), + $qb->expr()->isNull('availability.deletedAt') )) ->orderBy('availability.dateFrom', 'ASC') ->setParameter('today', new \DateTimeImmutable()) @@ -53,7 +54,8 @@ class AvailabilityRepository extends ServiceEntityRepository $qb->expr()->orX( $qb->expr()->isNull('availability.owner'), $qb->expr()->eq('availability.owner', ':owner') - ) + ), + $qb->expr()->isNull('availability.deletedAt') )) ->orderBy('availability.dateFrom', 'ASC') ->setParameter('teamer', $teamer) diff --git a/src/Repository/DestinationRepository.php b/src/Repository/DestinationRepository.php index 7265baf..38c7b1a 100644 --- a/src/Repository/DestinationRepository.php +++ b/src/Repository/DestinationRepository.php @@ -29,12 +29,16 @@ class DestinationRepository extends ServiceEntityRepository $qb = $this->createQueryBuilder('destination'); $dates = $qb - ->where($qb->expr()->orX( - $qb->expr()->like('destination.product', ':search'), - $qb->expr()->like('destination.hotel', ':search'), - $qb->expr()->like('DATE_FORMAT(destination.dateFrom, \'%d.%m.%y\')', ':search'), - $qb->expr()->like('DATE_FORMAT(destination.dateTo, \'%d.%m.%y\')', ':search') - )) + ->where( + $qb->expr()->andX( + $qb->expr()->isNull('destination.deletedAt'), + $qb->expr()->orX( + $qb->expr()->like('destination.product', ':search'), + $qb->expr()->like('destination.hotel', ':search'), + $qb->expr()->like('DATE_FORMAT(destination.dateFrom, \'%d.%m.%y\')', ':search'), + $qb->expr()->like('DATE_FORMAT(destination.dateTo, \'%d.%m.%y\')', ':search') + )) + ) ->setParameter('search', '%'.$this->escapeLikeWildcards($search).'%') ->orderBy('destination.dateFrom', 'ASC') ->addOrderBy('destination.product', 'ASC') diff --git a/src/Repository/FeeRepository.php b/src/Repository/FeeRepository.php index 4fde4d7..f5f8f55 100644 --- a/src/Repository/FeeRepository.php +++ b/src/Repository/FeeRepository.php @@ -21,46 +21,15 @@ class FeeRepository extends ServiceEntityRepository parent::__construct($registry, Fee::class); } - public function save(Fee $entity, bool $flush = false): void + public function getList(): array { - $this->getEntityManager()->persist($entity); + $qb = $this->createQueryBuilder('fee'); - if ($flush) { - $this->getEntityManager()->flush(); - } + return $qb + ->where($qb->expr()->isNull('fee.deletedAt')) + ->orderBy('fee.name', 'ASC') + ->getQuery() + ->getResult() + ; } - - public function remove(Fee $entity, bool $flush = false): void - { - $this->getEntityManager()->remove($entity); - - if ($flush) { - $this->getEntityManager()->flush(); - } - } - -// /** -// * @return Fee[] Returns an array of Fee objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('f') -// ->andWhere('f.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('f.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } - -// public function findOneBySomeField($value): ?Fee -// { -// return $this->createQueryBuilder('f') -// ->andWhere('f.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } } diff --git a/src/Repository/JobProfileRepository.php b/src/Repository/JobProfileRepository.php index 2f8e180..f8b1268 100644 --- a/src/Repository/JobProfileRepository.php +++ b/src/Repository/JobProfileRepository.php @@ -28,6 +28,7 @@ class JobProfileRepository extends ServiceEntityRepository return $qb ->select('job_profile', 'required_training') ->leftJoin('job_profile.requiredTrainings', 'required_training') + ->where($qb->expr()->isNull('job_profile.deletedAt')) ->orderBy('job_profile.name', 'ASC') ->getQuery() ->getResult() diff --git a/src/Repository/TrainingRepository.php b/src/Repository/TrainingRepository.php index 707761b..fafd59f 100644 --- a/src/Repository/TrainingRepository.php +++ b/src/Repository/TrainingRepository.php @@ -28,6 +28,7 @@ class TrainingRepository extends ServiceEntityRepository return $qb ->select('training', 'training_attendance') ->leftJoin('training.trainingAttendances', 'training_attendance') + ->where($qb->expr()->isNull('training.deletedAt')) ->orderBy('training.name', 'ASC') ->getQuery() ->getResult() diff --git a/templates/admin/assignment/index.html.twig b/templates/admin/assignment/index.html.twig index 954183b..4ea9607 100644 --- a/templates/admin/assignment/index.html.twig +++ b/templates/admin/assignment/index.html.twig @@ -65,6 +65,16 @@