This commit is contained in:
Björn Fromme
2023-10-08 12:37:44 +02:00
parent 8740041e7a
commit 8e3499581a
35 changed files with 119 additions and 1109 deletions
+45 -43
View File
@@ -45,14 +45,9 @@ class BpnImportCommand extends Command
return Command::FAILURE;
}
// Flush dates
$this
->connection
->executeQuery('TRUNCATE TABLE bpn_date')
;
$io->info('Found '.$totalCount.' XML files');
$datesCount = 0;
$addedCount = 0;
$updatedCount = 0;
// Iterate over xml files
foreach ($xmlFiles as $xmlFile) {
@@ -60,26 +55,17 @@ class BpnImportCommand extends Command
// Load xml file into simplexml object
$xml = simplexml_load_file($xmlFile);
// Iterate over all dates
foreach ($xml->xpath('reise/termin') as $dateXml) {
$product = (string) $dateXml->xpath('text')[0];
$busProId = (int) $dateXml->attributes()['idbuspro'];
$code = (string) $dateXml->attributes()['code'];
$dateFrom = \DateTimeImmutable::createFromFormat('d.m.Y', (string) $dateXml->attributes()['termin']);
$dateTo = \DateTimeImmutable::createFromFormat('d.m.Y', (string) $dateXml->attributes()['bis']);
$bus = false;
// Iterate over all service entries and look for 'bus'
foreach ($dateXml->xpath('lei_befoerderung/leistung') as $serviceXml) {
if ('BUS' === (string) $serviceXml->attributes()['unterart']) {
$bus = true;
break;
}
}
// Iterate over all destinations
foreach ($xml->xpath('reise/termin') as $destinationXml) {
$product = (string) $destinationXml->xpath('text')[0];
$busProId = (int) $destinationXml->attributes()['idbuspro'];
$code = (string) $destinationXml->attributes()['code'];
$dateFrom = \DateTimeImmutable::createFromFormat('d.m.Y', (string) $destinationXml->attributes()['termin']);
$dateTo = \DateTimeImmutable::createFromFormat('d.m.Y', (string) $destinationXml->attributes()['bis']);
// Find pickups
$datePickups = [];
foreach ($dateXml->xpath('zustiege/zustieg') as $pickupXml) {
foreach ($destinationXml->xpath('zustiege/zustieg') as $pickupXml) {
$pickupBusProId = (int) $pickupXml->attributes()['idbuspro'];
if ($pickupBusProId) {
$pickup = $this->pickupDataProvider->get($pickupBusProId);
@@ -93,32 +79,48 @@ class BpnImportCommand extends Command
}
// Iterate over all hotel entries
foreach ($dateXml->xpath('hotel') as $hotelXml) {
foreach ($destinationXml->xpath('hotel') as $hotelXml) {
$hotelBusProId = (int) $hotelXml->attributes()['idbuspro'];
$hotel = $this->hotelDataProvider->get($hotelBusProId);
// Finally store collected data
$this
->connection
->insert('bpn_date', [
'code' => $code,
'bus_pro_id' => $busProId,
'date_from' => $dateFrom->format('Y-m-d'),
'date_to' => $dateTo->format('Y-m-d'),
'product' => $product,
'hotel' => $hotel->getName(),
'hotel_code' => $hotel->getCode(),
'hotel_bus_pro_id' => $hotelBusProId,
'bus' => (int) $bus,
'pickups' => json_encode($datePickups),
])
;
++$datesCount;
// Finally update or store collected data
if ($id = $this->connection->fetchOne('SELECT id FROM destination WHERE bus_pro_id=? AND hotel_bus_pro_id=?', [$busProId, $hotelBusProId])) {
$this
->connection
->update('destination', [
'code' => $code,
'date_from' => $dateFrom->format('Y-m-d'),
'date_to' => $dateTo->format('Y-m-d'),
'product' => $product,
'pickups' => json_encode($datePickups),
], [
'id' => $id,
'hotel_bus_pro_id' => $hotelBusProId,
])
;
++$updatedCount;
} else {
$this
->connection
->insert('destination', [
'code' => $code,
'bus_pro_id' => $busProId,
'date_from' => $dateFrom->format('Y-m-d'),
'date_to' => $dateTo->format('Y-m-d'),
'product' => $product,
'hotel' => $hotel->getName(),
'hotel_code' => $hotel->getCode(),
'hotel_bus_pro_id' => $hotelBusProId,
'pickups' => json_encode($datePickups),
])
;
++$addedCount;
}
}
}
}
$io->info('Imported '.$datesCount.' dates');
$io->info('Added '.$addedCount.' and updated '.$updatedCount.' destinations');
return Command::SUCCESS;
}
@@ -2,7 +2,7 @@
namespace App\Controller\Admin\Autocomplete;
use App\Repository\BpnDateRepository;
use App\Repository\DestinationRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -11,7 +11,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
class BpnDateController extends AbstractController
{
public function __construct(private readonly BpnDateRepository $bpnDateRepository)
public function __construct(private readonly DestinationRepository $bpnDateRepository)
{}
#[Route('/admin/autocomplete/bpndate', name: 'app_admin_autocomplete_bpndate')]
+13 -4
View File
@@ -6,13 +6,13 @@ use App\Entity\Traits\BlameableEntity;
use App\Entity\Traits\TimestampableEntity;
use App\Model\BenefitsDto;
use App\Repository\AssignmentRepository;
use Carbon\CarbonPeriod;
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;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Entity(repositoryClass: AssignmentRepository::class)]
class Assignment implements BlameableEntityInterface, TimestampableEntityInterface
@@ -30,7 +30,7 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
#[ORM\ManyToOne]
#[Assert\NotNull(message: 'Bitte gib die Destination an')]
private ?BpnDate $destination = null;
private ?Destination $destination = null;
#[ORM\ManyToOne]
#[Assert\NotNull(message: 'Bitte gib das Jobprofil an')]
@@ -91,12 +91,12 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
return $this->uuid;
}
public function getDestination(): ?BpnDate
public function getDestination(): ?Destination
{
return $this->destination;
}
public function setDestination(?BpnDate $destination): static
public function setDestination(?Destination $destination): static
{
$this->destination = $destination;
@@ -151,6 +151,15 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
return $this;
}
public function getTotalPeriod(): CarbonPeriod
{
$destination = $this->getDestination();
$dateFrom = $this->getDateFrom() ?? $destination->getDateFrom();
$dateTo = $this->getDateTo() ?? $destination->getDateTo();
return new CarbonPeriod($dateFrom, $dateTo);
}
public function getPickupDate(): ?\DateTimeImmutable
{
return $this->pickupDate;
@@ -2,12 +2,12 @@
namespace App\Entity;
use App\Repository\BpnDateRepository;
use App\Repository\DestinationRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: BpnDateRepository::class)]
class BpnDate
#[ORM\Entity(repositoryClass: DestinationRepository::class)]
class Destination
{
#[ORM\Id]
#[ORM\GeneratedValue]
@@ -26,9 +26,6 @@ class BpnDate
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeImmutable $dateTo = null;
#[ORM\Column]
private ?bool $bus;
#[ORM\Column(length: 255)]
private ?string $product = null;
@@ -44,11 +41,6 @@ class BpnDate
#[ORM\Column]
private array $pickups = [];
public function __construct()
{
$this->bus = false;
}
public function __toString(): string
{
return sprintf('%s - %s: %s, %s',
@@ -100,18 +92,6 @@ class BpnDate
return $this;
}
public function isBus(): ?bool
{
return $this->bus;
}
public function setBus(bool $bus): static
{
$this->bus = $bus;
return $this;
}
public function getCode(): ?string
{
return $this->code;
@@ -183,4 +163,9 @@ class BpnDate
return $this;
}
public function hasBusTransfer(): bool
{
return 0 < count($this->getPickups());
}
}
-66
View File
@@ -1,66 +0,0 @@
<?php
namespace App\Entity;
use App\Repository\DispositionRequirementRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: DispositionRequirementRepository::class)]
class DispositionRequirement
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne]
private ?Training $training = null;
#[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $pickupDate = null;
#[ORM\ManyToOne(inversedBy: 'requirements')]
private ?Assignment $assignment = null;
public function getId(): ?int
{
return $this->id;
}
public function getTraining(): ?Training
{
return $this->training;
}
public function setTraining(?Training $training): static
{
$this->training = $training;
return $this;
}
public function getPickupDate(): ?\DateTimeImmutable
{
return $this->pickupDate;
}
public function setPickupDate(?\DateTimeImmutable $pickupDate): static
{
$this->pickupDate = $pickupDate;
return $this;
}
public function getAssignment(): ?Assignment
{
return $this->assignment;
}
public function setAssignment(?Assignment $assignment): static
{
$this->assignment = $assignment;
return $this;
}
}
+3 -5
View File
@@ -3,7 +3,7 @@
namespace App\Form;
use App\Entity\Assignment;
use App\Entity\BpnDate;
use App\Entity\Destination;
use App\Entity\Fee;
use App\Entity\JobProfile;
use App\Entity\User;
@@ -28,11 +28,9 @@ class AssignmentType extends AbstractType
])
->add('destination', AutocompleteEntityType::class, [
'label' => 'Destination',
'class' => BpnDate::class,
'class' => Destination::class,
'label_property' => 'product',
'label_function' => function (BpnDate $date) {
return (string) $date;
},
'label_function' => fn(Destination $destination) => (string) $destination,
'endpoint_route' => 'app_admin_autocomplete_bpndate',
])
->add('jobProfile', EntityType::class, [
+2 -1
View File
@@ -24,7 +24,7 @@ class TeamerProfileType extends AbstractType
->add('gender', ChoiceType::class, [
'label' => 'Geschlecht',
'choices' => [
'weiblich' => 'W',
'weiblich' => 'F',
'männlich' => 'M',
'divers' => 'D',
],
@@ -50,6 +50,7 @@ class TeamerProfileType extends AbstractType
->add('dateOfBirth', BirthdayType::class, [
'label' => 'Geburtsdatum',
'input_format' => 'datetime_immutable',
'widget' => 'choice',
])
->add('nationality', BpnCountryType::class, [
'label' => 'Nationalität',
@@ -2,41 +2,41 @@
namespace App\Repository;
use App\Entity\BpnDate;
use App\Entity\Destination;
use App\Repository\Traits\QueryHelperTrait;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<BpnDate>
* @extends ServiceEntityRepository<Destination>
*
* @method BpnDate|null find($id, $lockMode = null, $lockVersion = null)
* @method BpnDate|null findOneBy(array $criteria, array $orderBy = null)
* @method BpnDate[] findAll()
* @method BpnDate[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @method Destination|null find($id, $lockMode = null, $lockVersion = null)
* @method Destination|null findOneBy(array $criteria, array $orderBy = null)
* @method Destination[] findAll()
* @method Destination[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class BpnDateRepository extends ServiceEntityRepository
class DestinationRepository extends ServiceEntityRepository
{
use QueryHelperTrait;
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, BpnDate::class);
parent::__construct($registry, Destination::class);
}
public function getAutocompletionData(string $search): array
{
$qb = $this->createQueryBuilder('bpn_date');
$qb = $this->createQueryBuilder('destination');
$dates = $qb
->where($qb->expr()->orX(
$qb->expr()->like('bpn_date.product', ':product'),
$qb->expr()->like('bpn_date.hotel', ':hotel')
$qb->expr()->like('destination.product', ':product'),
$qb->expr()->like('destination.hotel', ':hotel')
))
->setParameter('product', '%'.$this->escapeLikeWildcards($search).'%')
->setParameter('hotel', '%'.$this->escapeLikeWildcards($search).'%')
->orderBy('bpn_date.dateFrom', 'ASC')
->addOrderBy('bpn_date.product', 'ASC')
->orderBy('destination.dateFrom', 'ASC')
->addOrderBy('destination.product', 'ASC')
->getQuery()
->getResult()
;
@@ -1,66 +0,0 @@
<?php
namespace App\Repository;
use App\Entity\DispositionRequirement;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<DispositionRequirement>
*
* @method DispositionRequirement|null find($id, $lockMode = null, $lockVersion = null)
* @method DispositionRequirement|null findOneBy(array $criteria, array $orderBy = null)
* @method DispositionRequirement[] findAll()
* @method DispositionRequirement[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class DispositionRequirementRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, DispositionRequirement::class);
}
public function save(DispositionRequirement $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
public function remove(DispositionRequirement $entity, bool $flush = false): void
{
$this->getEntityManager()->remove($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
// /**
// * @return DispositionRequirement[] Returns an array of DispositionRequirement objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('d')
// ->andWhere('d.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('d.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?DispositionRequirement
// {
// return $this->createQueryBuilder('d')
// ->andWhere('d.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}