WIP: Implement even more stuff
This commit is contained in:
@@ -49,6 +49,7 @@ export default class extends Controller {
|
||||
new Autocomplete(this.element, {
|
||||
search: searchHandler,
|
||||
getResultValue: result => result.text,
|
||||
submitOnEnter: true,
|
||||
onSubmit: submitHandler,
|
||||
debounceTime: 250,
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ import { German } from 'flatpickr/dist/l10n/de';
|
||||
export default class extends Controller {
|
||||
|
||||
static targets = [ 'field' ]
|
||||
static values = { format: String, minDate: String, maxDate: String, disableWeekends: Boolean }
|
||||
static values = { format: String, minDate: String, maxDate: String, disableWeekends: Boolean, mode: String }
|
||||
|
||||
initialize() {
|
||||
flatpickr.localize(German);
|
||||
@@ -17,10 +17,12 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
connect() {
|
||||
const mode = this.modeValue || 'single'
|
||||
const dateFormat = this.formatValue || 'd.m.Y'
|
||||
const minDate = this.minDateValue
|
||||
const maxDate = this.maxDateValue
|
||||
const options = {
|
||||
mode,
|
||||
dateFormat: 'Y-m-d',
|
||||
altInput: true,
|
||||
altFormat: dateFormat,
|
||||
|
||||
@@ -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 Version20231004134943 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 job_profile_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE assignment ADD CONSTRAINT FK_30C544BAA68D82A5 FOREIGN KEY (job_profile_id) REFERENCES job_profile (id)');
|
||||
$this->addSql('CREATE INDEX IDX_30C544BAA68D82A5 ON assignment (job_profile_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_30C544BAA68D82A5');
|
||||
$this->addSql('DROP INDEX IDX_30C544BAA68D82A5 ON assignment');
|
||||
$this->addSql('ALTER TABLE assignment DROP job_profile_id');
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,10 @@ class ApiClient
|
||||
{
|
||||
public const TYPE_NOTIFICATION = 'HINWEIS';
|
||||
public const TYPE_CUSTOMER_DATA = 'KUNDENKONTO';
|
||||
public const TYPE_PRODUCTS = 'PRODUKTE';
|
||||
public const TYPE_BASE_DATA_COUNTRIES = 'STAMMLAENDER';
|
||||
public const TYPE_BASE_DATA_PICKUPS = 'STAMMZUSTIEGE';
|
||||
public const TYPE_BASE_DATA_HOTELS = 'STAMMHOTELS';
|
||||
|
||||
private array $config;
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ use App\BusProNet\Model\Country;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class Countries
|
||||
class CountryDataProvider
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataProvider;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\ApiClientException;
|
||||
use App\BusProNet\Model\Hotel;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class HotelDataProvider
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
try {
|
||||
$hotels = $this->cache->get('bpn_hotels', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
return $this
|
||||
->apiClient
|
||||
->getBaseData(ApiClient::TYPE_BASE_DATA_HOTELS)
|
||||
->getItems()
|
||||
;
|
||||
});
|
||||
} catch (ApiClientException $e) {
|
||||
$hotels = [];
|
||||
}
|
||||
|
||||
return $hotels;
|
||||
}
|
||||
|
||||
public function get(int $busProId): ?Hotel
|
||||
{
|
||||
return $this->getAll()[$busProId] ?? null;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ use App\BusProNet\Model\Pickup;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class Pickups
|
||||
class PickupDataProvider
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataProvider;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\ApiClientException;
|
||||
use App\BusProNet\Model\Product;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class ProductDataProvider
|
||||
{
|
||||
public function __construct(private readonly ApiClient $apiClient, private readonly CacheInterface $cache)
|
||||
{}
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
try {
|
||||
$products = $this->cache->get('bpn_products', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
return $this
|
||||
->apiClient
|
||||
->getBaseData(ApiClient::TYPE_PRODUCTS)
|
||||
->getItems()
|
||||
;
|
||||
});
|
||||
} catch (ApiClientException $e) {
|
||||
$products = [];
|
||||
}
|
||||
|
||||
return $products;
|
||||
}
|
||||
|
||||
public function get(int $busProId): ?Product
|
||||
{
|
||||
return $this->getAll()[$busProId] ?? null;
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,11 @@ namespace App\BusProNet\Model;
|
||||
|
||||
class BaseDataResponse
|
||||
{
|
||||
private array $items = [];
|
||||
public function __construct(private readonly array $items)
|
||||
{}
|
||||
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
public function setItems(array $items): static
|
||||
{
|
||||
$this->items = $items;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class Hotel
|
||||
{
|
||||
private ?int $id = null;
|
||||
private ?int $busProId = null;
|
||||
private ?string $code = null;
|
||||
private ?string $name = null;
|
||||
private ?string $city = null;
|
||||
private ?string $street = null;
|
||||
private ?string $phone = null;
|
||||
private ?string $type = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(?int $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBusProId(): ?int
|
||||
{
|
||||
return $this->busProId;
|
||||
}
|
||||
|
||||
public function setBusProId(?int $busProId): static
|
||||
{
|
||||
$this->busProId = $busProId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCode(): ?string
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(?string $code): static
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(?string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCity(): ?string
|
||||
{
|
||||
return $this->city;
|
||||
}
|
||||
|
||||
public function setCity(?string $city): static
|
||||
{
|
||||
$this->city = $city;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStreet(): ?string
|
||||
{
|
||||
return $this->street;
|
||||
}
|
||||
|
||||
public function setStreet(?string $street): static
|
||||
{
|
||||
$this->street = $street;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPhone(): ?string
|
||||
{
|
||||
return $this->phone;
|
||||
}
|
||||
|
||||
public function setPhone(?string $phone): static
|
||||
{
|
||||
$this->phone = $phone;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(?string $type): static
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class Product
|
||||
{
|
||||
private ?int $id = null;
|
||||
private ?string $code = null;
|
||||
private ?string $name = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(?int $id): static
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCode(): ?string
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(?string $code): static
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(?string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,15 @@ namespace App\BusProNet;
|
||||
|
||||
use App\BusProNet\Model\Address;
|
||||
use App\BusProNet\Model\BaseDataResponse;
|
||||
use App\BusProNet\Model\NotificationResponse;
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\BusProNet\Model\Country;
|
||||
use App\BusProNet\Model\CrmAttribute;
|
||||
use App\BusProNet\Model\CrmAttributeGroup;
|
||||
use App\BusProNet\Model\CrmAttributesResponse;
|
||||
use App\BusProNet\Model\Hotel;
|
||||
use App\BusProNet\Model\NotificationResponse;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Product;
|
||||
use App\BusProNet\Model\ProfileResponse;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
@@ -55,6 +57,10 @@ class ResponseParser
|
||||
return $this->createCountriesResponse($xml);
|
||||
case ApiClient::TYPE_BASE_DATA_PICKUPS:
|
||||
return $this->createPickupsResponse($xml);
|
||||
case ApiClient::TYPE_BASE_DATA_HOTELS:
|
||||
return $this->createHotelsResponse($xml);
|
||||
case ApiClient::TYPE_PRODUCTS:
|
||||
return $this->createProductsResponse($xml);
|
||||
}
|
||||
|
||||
throw new ResponseParserException('Unable to parse XML response');
|
||||
@@ -187,10 +193,7 @@ class ResponseParser
|
||||
$countries[$token] = $country;
|
||||
}
|
||||
|
||||
$response = new BaseDataResponse();
|
||||
$response->setItems($countries);
|
||||
|
||||
return $response;
|
||||
return new BaseDataResponse($countries);
|
||||
}
|
||||
|
||||
public function createPickupsResponse(\SimpleXMLElement $xml): BaseDataResponse
|
||||
@@ -211,10 +214,53 @@ class ResponseParser
|
||||
$pickups[$busProId] = $pickup;
|
||||
}
|
||||
|
||||
$response = new BaseDataResponse();
|
||||
$response->setItems($pickups);
|
||||
return new BaseDataResponse($pickups);
|
||||
}
|
||||
|
||||
return $response;
|
||||
public function createHotelsResponse(\SimpleXMLElement $xml): BaseDataResponse
|
||||
{
|
||||
$hotels = [];
|
||||
|
||||
foreach ($xml->xpath('hotel') as $item) {
|
||||
$id = (int) $item->attributes()['id'];
|
||||
$busProId = (int) $item->attributes()['idbuspro'];
|
||||
$hotel = new Hotel();
|
||||
$hotel
|
||||
->setId($id)
|
||||
->setBusProId($busProId)
|
||||
->setCode((string) $item->attributes()['code'])
|
||||
->setName($item->xpath('name') ? (string) $item->xpath('name')[0] : null)
|
||||
->setCity($item->xpath('ort') ? (string) $item->xpath('ort')[0] : null)
|
||||
->setStreet($item->xpath('strasse') ? (string) $item->xpath('strasse')[0] : null)
|
||||
->setPhone($item->xpath('telefon') ? (string) $item->xpath('telefon')[0] : null)
|
||||
->setType($item->xpath('art') ? (string) $item->xpath('art')[0] : null)
|
||||
;
|
||||
$hotels[$busProId] = $hotel;
|
||||
}
|
||||
|
||||
return new BaseDataResponse($hotels);
|
||||
}
|
||||
|
||||
public function createProductsResponse(\SimpleXMLElement $xml): BaseDataResponse
|
||||
{
|
||||
$products = [];
|
||||
|
||||
foreach ($xml->xpath('produkte/produkt') as $item) {
|
||||
$code = (string) $item->attributes()['code'];
|
||||
if (true === empty($code)) {
|
||||
continue;
|
||||
}
|
||||
$id = (int) $item->attributes()['id'];
|
||||
$product = new Product();
|
||||
$product
|
||||
->setId($id)
|
||||
->setName((string) $item->attributes()['bezeichnung'])
|
||||
->setCode($code)
|
||||
;
|
||||
$products[$id] = $product;
|
||||
}
|
||||
|
||||
return new BaseDataResponse($products);
|
||||
}
|
||||
|
||||
private function resolveOptions(array $options): array
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Assignment;
|
||||
|
||||
use App\Entity\Assignment;
|
||||
use App\Form\AssignmentType;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
#[Route('/admin/assignment/create', name: 'app_admin_assignment_create')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$assignment = new Assignment();
|
||||
$form = $this->createForm(AssignmentType::class, $assignment);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
return $this->redirectToRoute('app_admin_assignment_index');
|
||||
}
|
||||
|
||||
return $this->render('admin/assignment/create.html.twig', [
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Autocomplete;
|
||||
|
||||
use App\BusProNet\DataProvider\HotelDataProvider;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class HotelController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly HotelDataProvider $hotelDataProvider)
|
||||
{}
|
||||
|
||||
#[Route('/admin/autocomplete/hotel', name: 'app_admin_autocomplete_hotel')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$query = json_decode($request->getContent(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$queryString = $query['search'];
|
||||
} catch (\JsonException $e) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$hotels = $this->hotelDataProvider->getAll();
|
||||
$data = [];
|
||||
|
||||
foreach ($hotels as $hotel) {
|
||||
$name = $hotel->getName();
|
||||
if (1 === preg_match('/'.preg_quote($queryString, '/').'/i', $name)) {
|
||||
$data[] = [
|
||||
'value' => $hotel->getId(),
|
||||
'text' => sprintf('%s (%s)', $name, $hotel->getCode()),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->json($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Autocomplete;
|
||||
|
||||
use App\BusProNet\DataProvider\ProductDataProvider;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class ProductController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly ProductDataProvider $productDataProvider)
|
||||
{}
|
||||
|
||||
#[Route('/admin/autocomplete/product', name: 'app_admin_autocomplete_product')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$query = json_decode($request->getContent(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$queryString = $query['search'];
|
||||
} catch (\JsonException $e) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$products = $this->productDataProvider->getAll();
|
||||
$data = [];
|
||||
|
||||
foreach ($products as $product) {
|
||||
$name = $product->getName();
|
||||
if (1 === preg_match('/'.preg_quote($queryString, '/').'/i', $name)) {
|
||||
$data[] = [
|
||||
'value' => $product->getId(),
|
||||
'text' => sprintf('%s (%s)', $name, $product->getCode()),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->json($data);
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,13 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
#[ORM\Column(type: 'string', length: 36, unique: true)]
|
||||
private string $uuid;
|
||||
|
||||
#[ORM\Column(length: 64)]
|
||||
private ?string $busProCode = null;
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $destinationBusProId = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[ORM\ManyToOne]
|
||||
private ?JobProfile $jobProfile = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $available = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
@@ -37,6 +40,12 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
private ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
private ?\DateTimeImmutable $pickupDate = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $pickup = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
private ?string $benefits = null;
|
||||
|
||||
@@ -77,14 +86,26 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
public function getBusProCode(): ?string
|
||||
public function getDestinationBusProId(): ?int
|
||||
{
|
||||
return $this->busProCode;
|
||||
return $this->destinationBusProId;
|
||||
}
|
||||
|
||||
public function setBusProCode(string $busProCode): static
|
||||
public function setDestinationBusProId(?int $destinationBusProId): static
|
||||
{
|
||||
$this->busProCode = $busProCode;
|
||||
$this->destinationBusProId = $destinationBusProId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getJobProfile(): ?JobProfile
|
||||
{
|
||||
return $this->jobProfile;
|
||||
}
|
||||
|
||||
public function setJobProfile(?JobProfile $jobProfile): static
|
||||
{
|
||||
$this->jobProfile = $jobProfile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -94,7 +115,7 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
return $this->available;
|
||||
}
|
||||
|
||||
public function setAvailable(int $available): static
|
||||
public function setAvailable(?int $available): static
|
||||
{
|
||||
$this->available = $available;
|
||||
|
||||
@@ -125,6 +146,30 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPickupDate(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->pickupDate;
|
||||
}
|
||||
|
||||
public function setPickupDate(?\DateTimeImmutable $pickupDate): static
|
||||
{
|
||||
$this->pickupDate = $pickupDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPickup(): ?int
|
||||
{
|
||||
return $this->pickup;
|
||||
}
|
||||
|
||||
public function setPickup(?int $pickup): static
|
||||
{
|
||||
$this->pickup = $pickup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBenefits(): ?string
|
||||
{
|
||||
return $this->benefits;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Assignment;
|
||||
use App\Entity\Fee;
|
||||
use App\Entity\JobProfile;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AssignmentType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('available', IntegerType::class, [
|
||||
'label' => 'Anzahl',
|
||||
'required' => false,
|
||||
])
|
||||
->add('destinationBusProId', AutocompleteChoiceType::class, [
|
||||
'label' => 'Destination',
|
||||
'endpoint_route' => 'app_admin_autocomplete_hotel',
|
||||
])
|
||||
->add('jobProfile', EntityType::class, [
|
||||
'label' => 'Jobprofil',
|
||||
'class' => JobProfile::class,
|
||||
'choice_label' => 'name',
|
||||
'placeholder' => 'Bitte auswählen',
|
||||
])
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Einsatztermin von',
|
||||
'mode' => 'range',
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Einsatztermin bis',
|
||||
])
|
||||
->add('pickupDate', DatepickerType::class, [
|
||||
'label' => 'Busabfahrt',
|
||||
'required' => false,
|
||||
])
|
||||
->add('pickup', BpnPickupType::class, [
|
||||
'label' => 'Buszustieg',
|
||||
'required' => false,
|
||||
'placeholder' => 'Keine Busbegleitung',
|
||||
])
|
||||
->add('benefits', TextareaType::class, [
|
||||
'label' => 'Benefits',
|
||||
'required' => false,
|
||||
])
|
||||
->add('fees', EntityType::class, [
|
||||
'label' => 'Honorar(e)',
|
||||
'class' => Fee::class,
|
||||
'choice_label' => 'name',
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Assignment::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
class AutocompleteChoiceType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly UrlGeneratorInterface $urlGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'endpoint_route' => null,
|
||||
'choices' => [],
|
||||
'compound' => false,
|
||||
'placeholder' => null,
|
||||
'endpoint_parameters' => [],
|
||||
'controller_action' => null,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('choices', 'array');
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
if ($options['endpoint_route']) {
|
||||
$view->vars['endpoint_url'] = $this->urlGenerator->generate($options['endpoint_route'], $options['endpoint_parameters']);
|
||||
} else {
|
||||
$view->vars['choices'] = $options['choices'];
|
||||
}
|
||||
$view->vars['placeholder'] = $options['placeholder'];
|
||||
|
||||
$view->vars['initial_label'] = $form->getData();
|
||||
$view->vars['initial_value'] = $form->getData();
|
||||
$view->vars['action'] = $options['controller_action'];
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'autocomplete';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Form\DataTransformer\EntityToIdTransformer;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
class AutocompleteEntityType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly UrlGeneratorInterface $urlGenerator
|
||||
) {
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$dataTransformer = new EntityToIdTransformer($this->entityManager, $options['class']);
|
||||
$builder->addModelTransformer($dataTransformer);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setRequired(['class']);
|
||||
|
||||
$resolver->setDefaults([
|
||||
'endpoint_route' => null,
|
||||
'choices' => [],
|
||||
'compound' => false,
|
||||
'label_property' => 'label',
|
||||
'label_function' => null,
|
||||
'placeholder' => null,
|
||||
'endpoint_parameters' => [],
|
||||
'controller_action' => null,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('choices', 'array');
|
||||
$resolver->setAllowedTypes('label_function', ['null', 'callable']);
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
if ($options['endpoint_route']) {
|
||||
$view->vars['endpoint_url'] = $this->urlGenerator->generate($options['endpoint_route'], $options['endpoint_parameters']);
|
||||
} else {
|
||||
$view->vars['choices'] = $options['choices'];
|
||||
}
|
||||
$view->vars['label_property'] = $options['label_property'];
|
||||
$view->vars['placeholder'] = $options['placeholder'];
|
||||
|
||||
$view->vars['initial_label'] = '';
|
||||
$view->vars['initial_value'] = null;
|
||||
$view->vars['action'] = $options['controller_action'];
|
||||
|
||||
$entity = $form->getData();
|
||||
|
||||
if (null !== $entity) {
|
||||
if (null !== $options['label_function']) {
|
||||
$labelFunction = $options['label_function'];
|
||||
$view->vars['initial_label'] = $labelFunction($entity);
|
||||
} else {
|
||||
$getter = 'get'.ucfirst($options['label_property']);
|
||||
if (method_exists($entity, $getter)) {
|
||||
$view->vars['initial_label'] = $entity->$getter();
|
||||
}
|
||||
}
|
||||
$view->vars['initial_value'] = $entity->getId();
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'autocomplete';
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\BusProNet\DataProvider\Countries;
|
||||
use App\BusProNet\DataProvider\CountryDataProvider;
|
||||
use App\Form\ChoiceLoader\BpnCountryChoiceLoader;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceList;
|
||||
@@ -12,7 +12,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BpnCountryType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly Countries $countries)
|
||||
public function __construct(private readonly CountryDataProvider $countries)
|
||||
{}
|
||||
|
||||
public function getParent(): string
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\BusProNet\DataProvider\Pickups;
|
||||
use App\BusProNet\DataProvider\PickupDataProvider;
|
||||
use App\Form\ChoiceLoader\BpnPickupsChoiceLoader;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
@@ -10,7 +10,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BpnPickupType extends AbstractType
|
||||
{
|
||||
public function __construct(private readonly Pickups $pickups)
|
||||
public function __construct(private readonly PickupDataProvider $pickups)
|
||||
{}
|
||||
|
||||
public function getParent(): string
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Form\ChoiceLoader;
|
||||
|
||||
use App\BusProNet\DataProvider\Countries;
|
||||
use App\BusProNet\DataProvider\CountryDataProvider;
|
||||
use App\BusProNet\Model\Country;
|
||||
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
@@ -10,7 +10,7 @@ use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
|
||||
class BpnCountryChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
public function __construct(private readonly Countries $countries, private readonly string $property)
|
||||
public function __construct(private readonly CountryDataProvider $countries, private readonly string $property)
|
||||
{}
|
||||
|
||||
public function loadChoiceList(callable $value = null): ChoiceListInterface
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Form\ChoiceLoader;
|
||||
|
||||
use App\BusProNet\DataProvider\Pickups;
|
||||
use App\BusProNet\DataProvider\PickupDataProvider;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
@@ -10,7 +10,7 @@ use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
|
||||
class BpnPickupsChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
public function __construct(private readonly Pickups $pickups)
|
||||
public function __construct(private readonly PickupDataProvider $pickups)
|
||||
{}
|
||||
|
||||
public function loadChoiceList(callable $value = null): ChoiceListInterface
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form\ChoiceLoader;
|
||||
|
||||
use App\BusProNet\DataProvider\ProductDataProvider;
|
||||
use App\BusProNet\Model\Product;
|
||||
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
|
||||
class BpnProductsChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
public function __construct(private readonly ProductDataProvider $products)
|
||||
{}
|
||||
|
||||
public function loadChoiceList(callable $value = null): ChoiceListInterface
|
||||
{
|
||||
$choices = [];
|
||||
/** @var Product[] $products */
|
||||
$products = $this->products->getAll();
|
||||
|
||||
foreach ($products as $product) {
|
||||
$choices[$product->getName()] = $product->getId();
|
||||
}
|
||||
|
||||
ksort($choices);
|
||||
|
||||
return new ArrayChoiceList($choices);
|
||||
|
||||
}
|
||||
|
||||
public function loadChoicesForValues(array $values, callable $value = null): array
|
||||
{
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function loadValuesForChoices(array $choices, callable $value = null): array
|
||||
{
|
||||
return $choices;
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,13 @@ class DatepickerType extends AbstractType
|
||||
'min_date' => null,
|
||||
'max_date' => null,
|
||||
'disable_weekends' => false,
|
||||
'mode' => 'single', // 'single', 'multiple' or 'range'
|
||||
]);
|
||||
$resolver->setAllowedTypes('min_date', ['null', \DateTimeImmutable::class]);
|
||||
$resolver->setAllowedTypes('max_date', ['null', \DateTimeImmutable::class]);
|
||||
$resolver->setAllowedTypes('disable_weekends', 'bool');
|
||||
$resolver->setAllowedTypes('mode', 'string');
|
||||
$resolver->setAllowedValues('mode', ['single', 'multiple', 'range']);
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
@@ -30,6 +33,7 @@ class DatepickerType extends AbstractType
|
||||
$view->vars['min_date'] = $options['min_date'];
|
||||
$view->vars['max_date'] = $options['max_date'];
|
||||
$view->vars['disable_weekends'] = $options['disable_weekends'];
|
||||
$view->vars['mode'] = $options['mode'];
|
||||
}
|
||||
|
||||
public function getParent(): string
|
||||
|
||||
@@ -143,7 +143,9 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
|
||||
$menu->addChild('zurück zur Übersicht', [
|
||||
'route' => 'app_admin_teamer_index',
|
||||
'icon' => 'back',
|
||||
'extras' => [
|
||||
'icon' => 'back',
|
||||
],
|
||||
]);
|
||||
|
||||
return $menu;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Twig;
|
||||
|
||||
use App\BusProNet\DataProvider\Countries;
|
||||
use App\BusProNet\DataProvider\Pickups;
|
||||
use App\BusProNet\DataProvider\CountryDataProvider;
|
||||
use App\BusProNet\DataProvider\PickupDataProvider;
|
||||
use App\BusProNet\Model\Country;
|
||||
use App\Entity\Teamer;
|
||||
use Carbon\Carbon;
|
||||
@@ -15,11 +15,11 @@ use Twig\Extra\Intl\IntlExtension;
|
||||
class AppRuntime implements RuntimeExtensionInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly RequestStack $requestStack,
|
||||
private readonly IntlExtension $intlExtension,
|
||||
private readonly Countries $countries,
|
||||
private readonly Pickups $pickups,
|
||||
private readonly string $environment
|
||||
private readonly RequestStack $requestStack,
|
||||
private readonly IntlExtension $intlExtension,
|
||||
private readonly CountryDataProvider $countries,
|
||||
private readonly PickupDataProvider $pickups,
|
||||
private readonly string $environment
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
{% elseif item.extras.divider == true %}
|
||||
<hr class="my-4 h-px bg-gray-200">
|
||||
{% else %}
|
||||
<div class="hover:bg-gray-50 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold text-gray-700" role="button">
|
||||
<div class="hover:bg-gray-50 group flex gap-x-3 rounded-md p-2 text-sm leading-5 font-semibold text-gray-700" role="button">
|
||||
{{ block('label') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -73,8 +73,8 @@
|
||||
{% block label %}
|
||||
{% apply spaceless %}
|
||||
{% if item.extras.icon is defined %}
|
||||
{{ icon(item.extras.icon, 'h-6 w-6 shrink-0 text-gray-400') }}
|
||||
{{ item.label|raw }}
|
||||
{{ icon(item.extras.icon, 'h-5 w-5 shrink-0 text-gray-400') }}
|
||||
<span class="flex-1">{{ item.label|raw }}</span>
|
||||
{% else %}
|
||||
{{ item.label|raw }}
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einsatz anlegen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Einsatz anlegen
|
||||
</h1>
|
||||
{{ form_start(form) }}
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
@@ -98,14 +98,9 @@
|
||||
|
||||
{%- block choice_widget_expanded -%}
|
||||
<fieldset>
|
||||
{% if form.vars.label %}
|
||||
<legend class="text-base font-bold leading-6 text-gray-900">
|
||||
{{ form.vars.label }}
|
||||
</legend>
|
||||
{% endif %}
|
||||
<div class="mt-4 divide-y divide-gray-200 border-b border-t border-gray-200">
|
||||
<div class="divide-y divide-gray-200">
|
||||
{%- for child in form %}
|
||||
<div class="relative flex items-start py-4">
|
||||
<div class="relative flex items-start py-4 first:pt-0">
|
||||
<div class="min-w-0 flex-1 text-sm leading-6">
|
||||
<label for="{{ child.vars.id }}" class="select-none font-medium text-gray-900">
|
||||
{{ child.vars.label }}
|
||||
@@ -166,7 +161,7 @@
|
||||
{%- if disabled is defined and disabled == true -%}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
|
||||
{%- endif -%}
|
||||
<div {{ stimulus_controller('datepicker', { 'minDate': minDate, 'maxDate': maxDate, 'disableWeekends': form.vars.disable_weekends }) }}>
|
||||
<div {{ stimulus_controller('datepicker', { 'minDate': minDate, 'maxDate': maxDate, 'disableWeekends': form.vars.disable_weekends, 'mode': form.vars.mode }) }}>
|
||||
<input type="text" name="{{ form.vars.full_name }}" value="{{ value }}" {{ block('widget_attributes') }}
|
||||
{{ stimulus_target('datepicker', 'field') }} />
|
||||
</div>
|
||||
@@ -174,3 +169,41 @@
|
||||
<input type="hidden" name="{{ form.vars.full_name }}" value="{{ form.vars.value }}">
|
||||
{%- endif -%}
|
||||
{%- endblock datepicker_widget %}
|
||||
|
||||
{%- block autocomplete_widget -%}
|
||||
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' autocomplete-input block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6')|trim }) -%}
|
||||
{%- if errors|length -%}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
|
||||
{% else %}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-gray-400 focus:ring-primary' }) -%}
|
||||
{%- endif -%}
|
||||
{%- if disabled is defined and disabled == true -%}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
|
||||
{%- endif -%}
|
||||
<div class="autocomplete"
|
||||
data-controller="autocomplete"
|
||||
{% if form.vars.action %}data-action="{{ form.vars.action }}"{% endif %}
|
||||
{% if form.vars.endpoint_url is defined %}data-autocomplete-url-value="{{ form.vars.endpoint_url }}"{% endif %}
|
||||
{% if form.vars.choices is defined %}data-autocomplete-choices-value='{{ form.vars.choices | json_encode | raw }}'{% endif %}
|
||||
>
|
||||
<input type="text"
|
||||
class="{{ attr.class }}"
|
||||
value="{{ form.vars.initial_label }}"
|
||||
{{ stimulus_target('autocomplete', 'input') }}>
|
||||
<ul class="autocomplete-result-list"></ul>
|
||||
<input type="hidden"
|
||||
name="{{ form.vars.full_name }}"
|
||||
{{ stimulus_target('autocomplete', 'field') }}
|
||||
value="{{ form.vars.initial_value }}">
|
||||
<button type="button"
|
||||
class="autocomplete-icon hidden"
|
||||
{{ stimulus_action('autocomplete', 'reset') }}
|
||||
{{ stimulus_target('autocomplete', 'resetButton') }}>
|
||||
{{ icon('close', 'w-4 h-4 text-gray-700') }}
|
||||
</button>
|
||||
<div class="autocomplete-icon"
|
||||
{{ stimulus_target('autocomplete', 'searchIcon') }}>
|
||||
{{ icon('search', 'w-4 h-4 text-gray-700') }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock autocomplete_widget %}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Tests\BusProNet;
|
||||
|
||||
use App\BusProNet\ApiClient;
|
||||
use App\BusProNet\Model\BaseDataResponse;
|
||||
use App\BusProNet\Model\CrmAttributesResponse;
|
||||
use App\BusProNet\Model\Hotel;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\PickupsResponse;
|
||||
use App\BusProNet\Model\ProfileResponse;
|
||||
use App\BusProNet\ResponseParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -16,7 +18,7 @@ class ResponseParserTest extends TestCase
|
||||
$content = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="HINWEIS"><nr>853</nr><text>ID, EMail oder Passwort falsch</text></satz></ergebnis>';
|
||||
|
||||
$parser = $this->getParserInstance();
|
||||
$response = $parser->parseXmlString($content);
|
||||
$response = $parser->parseXmlString(ApiClient::TYPE_NOTIFICATION, $content);
|
||||
|
||||
$this->assertEquals(853, $response->getCode());
|
||||
$this->assertEquals('ID, EMail oder Passwort falsch', $response->getMessage());
|
||||
@@ -28,12 +30,9 @@ class ResponseParserTest extends TestCase
|
||||
$content = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="KUNDENKONTO"></satz><art>Adressdaten</art><idadresse>141747</idadresse><idperson>224526</idperson><adressdaten><name>Fromme</name><vorname>Björn</vorname><anrede>Herr</anrede><titel></titel><geschlecht>M</geschlecht><geburtsdatum>16.04.1972</geburtsdatum><nationalitaet>D</nationalitaet><anschrift><id>119447</id><strasse>Emilienstraße 57</strasse><plz>42853</plz><ort>Remscheid</ort><ortsteil></ortsteil><land>D</land></anschrift><kommunikation><telefonmobil></telefonmobil><email>[email protected]</email><newsletter>False</newsletter><telefonprivat>02191-4615837</telefonprivat></kommunikation></adressdaten></ergebnis>';
|
||||
|
||||
$parser = $this->getParserInstance();
|
||||
$response = $parser->parseXmlString($content);
|
||||
$response = $parser->parseXmlString(ApiClient::TYPE_CUSTOMER_DATA, $content);
|
||||
|
||||
$this->assertInstanceOf(ProfileResponse::class, $response);
|
||||
$this->assertNull($response->getCode());
|
||||
$this->assertNull($response->getMessage());
|
||||
$this->assertTrue($response->isSuccessful());
|
||||
}
|
||||
|
||||
public function testParseSuccessfulCrmAttributesResponse(): void
|
||||
@@ -41,26 +40,23 @@ class ResponseParserTest extends TestCase
|
||||
$content = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="KUNDENKONTO"></satz><art>SelektionCRM</art><idadresse>141747</idadresse><idperson>224526</idperson><selektionsmerkmale><selektionsgruppe id="6" bezeichnung="Gruppen - Art (NUR direkt dem GR-Kunden zuordnen)"><selektion id="1156" bezeichnung="Gruppen-Buchungsportal" aenderbar="False" auswahl="True"></selektion></selektionsgruppe><selektionsgruppe id="10" bezeichnung="TEAM"><selektion id="1070" bezeichnung="E&P Teamer - allg. Merkmal" aenderbar="False" auswahl="True"></selektion></selektionsgruppe><selektionsgruppe id="83" bezeichnung="Interessen"><selektion id="1064" bezeichnung="Sportclub-Reisen" aenderbar="True" auswahl="False"></selektion><selektion id="1065" bezeichnung="Individual-Ferienwohnungen/Gasthöfe" aenderbar="True" auswahl="False"></selektion><selektion id="1066" bezeichnung="Kurztrips" aenderbar="True" auswahl="False"></selektion><selektion id="1067" bezeichnung="Eventreisen" aenderbar="True" auswahl="False"></selektion><selektion id="1068" bezeichnung="Gruppen-Angebote" aenderbar="True" auswahl="False"></selektion><selektion id="1069" bezeichnung="Firmen-Angebote" aenderbar="True" auswahl="False"></selektion></selektionsgruppe></selektionsmerkmale><crmaktionen><crmaktion id="428" code="18DDW40" bezeichnung="Deal Der Woche KW40-2018" aenderbar="False" auswahl="False"></crmaktion><crmaktion id="276" code="NOMAIL" bezeichnung="Ich möchte keine Werbung per Mail erhalten" aenderbar="True" auswahl="True"></crmaktion></crmaktionen></ergebnis>';
|
||||
|
||||
$parser = $this->getParserInstance();
|
||||
$response = $parser->parseXmlString($content);
|
||||
$response = $parser->parseXmlString(ApiClient::TYPE_CUSTOMER_DATA, $content);
|
||||
|
||||
$this->assertInstanceOf(CrmAttributesResponse::class, $response);
|
||||
$this->assertNull($response->getCode());
|
||||
$this->assertNull($response->getMessage());
|
||||
$this->assertTrue($response->isSuccessful());
|
||||
$this->assertCount(3, $response->getAttributeGroups());
|
||||
$this->assertTrue($response->isTeamer());
|
||||
}
|
||||
|
||||
public function testParseSuccessfulPickupsResponse(): void
|
||||
{
|
||||
$content = '<?xml version="1.0" encoding="utf-8" ?><ergebnis><satz typ="STAMMZUSTIEGE"></satz><zustiege><zustieg id="1" idbuspro="1" code="298"><ort>Karlsruhe</ort><strasse>A5 - Autohof Bruchsal</strasse><art>BUS</art><hausabholung>False</hausabholung><crsbuchbar>True</crsbuchbar><internetbuchbar>True</internetbuchbar></zustieg><zustieg id="2" idbuspro="2" code="2"><ort>Bonn</ort><strasse>Bahnhof</strasse><art>BUS</art> <hausabholung>False</hausabholung><crsbuchbar>True</crsbuchbar><internetbuchbar>True</internetbuchbar></zustieg></zustiege></ergebnis>';
|
||||
$content = '<?xml version="1.0" encoding="utf-8" ?><zustiege><zustieg id="1" idbuspro="1" code="298"><ort>Karlsruhe</ort><strasse>A5 - Autohof Bruchsal</strasse><art>BUS</art><hausabholung>False</hausabholung><crsbuchbar>True</crsbuchbar><internetbuchbar>True</internetbuchbar></zustieg><zustieg id="2" idbuspro="2" code="2"><ort>Bonn</ort><strasse>Bahnhof</strasse><art>BUS</art><hausabholung>False</hausabholung><crsbuchbar>True</crsbuchbar><internetbuchbar>True</internetbuchbar></zustieg></zustiege>';
|
||||
|
||||
$parser = $this->getParserInstance();
|
||||
$response = $parser->parseXmlString($content);
|
||||
$response = $parser->parseXmlString(ApiClient::TYPE_BASE_DATA_PICKUPS, $content);
|
||||
|
||||
$this->assertInstanceOf(PickupsResponse::class, $response);
|
||||
$this->assertInstanceOf(BaseDataResponse::class, $response);
|
||||
|
||||
$pickups = $response->getPickups();
|
||||
$pickups = $response->getItems();
|
||||
$this->assertCount(2, $pickups);
|
||||
|
||||
$pickup = reset($pickups);
|
||||
@@ -72,6 +68,48 @@ class ResponseParserTest extends TestCase
|
||||
$this->assertEquals('A5 - Autohof Bruchsal', $pickup->getStreet());
|
||||
}
|
||||
|
||||
public function testParseSuccessfulHotelsResponse(): void
|
||||
{
|
||||
$content = '<?xml version="1.0" encoding="utf-8" ?><hotels><hotel id="1" idbuspro="202003" code="HÖCHST"><name>Berggasthof Höchsten</name><ort>Musterort</ort><strasse>Musterstr. 123</strasse><telefon>03444/19100</telefon><art>Gaststätte</art><internetbuchbar>True</internetbuchbar></hotel><hotel id="2" idbuspro="202004" code="Z. LÖW"><name>Brauereigasthof Zum Löwen</name><ort>Musterort</ort><strasse>Musterstr. 123</strasse><telefon>03437/11133</telefon><art>Gaststätte</art><internetbuchbar>True</internetbuchbar><selektiongruppe id="1" idbuspro="1" bezeichnung="Reisearten 1"><selektion id="1" idbuspro="2" bezeichnung="Kurz-und Clubreisen" /><selektion id="2" idbuspro="7" bezeichnung="Musik und Theater" /><selektion id="3" idbuspro="12" bezeichnung="Flugreisen" /><selektion id="4" idbuspro="13" bezeichnung="Tagesfahrten" /><selektion id="5" idbuspro="1" bezeichnung="Städtereisen" /></selektiongruppe><selektiongruppe id="2" idbuspro="2" bezeichnung="Reisearten 2"><selektion id="1" idbuspro="18" bezeichnung="Adventreisen" /></selektiongruppe><selektiongruppe id="3" idbuspro="3" bezeichnung="Statistik 1"><selektion id="1" idbuspro="31" bezeichnung="Städtreisen" /><selektion id="2" idbuspro="32" bezeichnung="Kurz-und Clubreisen" /><selektion id="3" idbuspro="37" bezeichnung="Musik und Theater" /><selektion id="4" idbuspro="42" bezeichnung="Flugreisen" /><selektion id="5" idbuspro="43" bezeichnung="Tagesfahrten" /></selektiongruppe></hotel></hotels>';
|
||||
|
||||
$parser = $this->getParserInstance();
|
||||
$response = $parser->parseXmlString(ApiClient::TYPE_BASE_DATA_HOTELS, $content);
|
||||
|
||||
$this->assertInstanceOf(BaseDataResponse::class, $response);
|
||||
|
||||
$hotels = $response->getItems();
|
||||
$this->assertCount(2, $hotels);
|
||||
|
||||
$hotel = reset($hotels);
|
||||
$this->assertInstanceOf(Hotel::class, $hotel);
|
||||
$this->assertEquals(1, $hotel->getId());
|
||||
$this->assertEquals(202003, $hotel->getBusProId());
|
||||
$this->assertEquals('HÖCHST', $hotel->getCode());
|
||||
$this->assertEquals('Berggasthof Höchsten', $hotel->getName());
|
||||
$this->assertEquals('Musterort', $hotel->getCity());
|
||||
$this->assertEquals('Musterstr. 123', $hotel->getStreet());
|
||||
$this->assertEquals('03444/19100', $hotel->getPhone());
|
||||
$this->assertEquals('Gaststätte', $hotel->getType());
|
||||
}
|
||||
|
||||
public function testParseSuccessfulProductsResponse(): void
|
||||
{
|
||||
$content = '<?xml version="1.0" encoding="utf-8" ?><ergebnis><satz typ="PRODUKTE" /><produkte><produkt id="389" code="ANDA" bezeichnung="Andalusien" /><produkt id="483" code="PORTFL" bezeichnung="Portugal -Algarve Flugreise" /><produkt id="490" code="MALL" bezeichnung="Mallorca Flugreise" /></produkte></ergebnis>';
|
||||
|
||||
$parser = $this->getParserInstance();
|
||||
$response = $parser->parseXmlString(ApiClient::TYPE_PRODUCTS, $content);
|
||||
|
||||
$this->assertInstanceOf(BaseDataResponse::class, $response);
|
||||
|
||||
$products = $response->getItems();
|
||||
$this->assertCount(3, $products);
|
||||
|
||||
$product = reset($products);
|
||||
$this->assertEquals(389, $product->getId());
|
||||
$this->assertEquals('ANDA', $product->getCode());
|
||||
$this->assertEquals('Andalusien', $product->getName());
|
||||
}
|
||||
|
||||
private function getParserInstance(): ResponseParser
|
||||
{
|
||||
return new ResponseParser([
|
||||
|
||||
Reference in New Issue
Block a user