feat: additional attribute for synced with bpn status including filtering by

closes #869anf53g
This commit is contained in:
Björn Fromme
2025-09-30 18:36:08 +02:00
parent 4b8971e194
commit e23a5097ef
10 changed files with 127 additions and 1 deletions
+3
View File
@@ -141,6 +141,9 @@
<!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --> <!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<path d="M376.1 71.03c-9.375-9.375-24.56-9.375-33.94 0l-336 336c-9.375 9.375-9.375 24.56 0 33.94C11.72 445.7 17.84 448 24 448s12.28-2.344 16.97-7.031l336-336C386.3 95.59 386.3 80.41 376.1 71.03zM64 176c26.51 0 48-21.49 48-48S90.51 80 64 80C37.49 80 16 101.5 16 128S37.49 176 64 176zM320 336c-26.51 0-48 21.49-48 48s21.49 48 48 48c26.51 0 48-21.49 48-48S346.5 336 320 336z"/> <path d="M376.1 71.03c-9.375-9.375-24.56-9.375-33.94 0l-336 336c-9.375 9.375-9.375 24.56 0 33.94C11.72 445.7 17.84 448 24 448s12.28-2.344 16.97-7.031l336-336C386.3 95.59 386.3 80.41 376.1 71.03zM64 176c26.51 0 48-21.49 48-48S90.51 80 64 80C37.49 80 16 101.5 16 128S37.49 176 64 176zM320 336c-26.51 0-48 21.49-48 48s21.49 48 48 48c26.51 0 48-21.49 48-48S346.5 336 320 336z"/>
</symbol> </symbol>
<symbol id="icon-chair" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M248 48H200V224H152V58.7c-23.9 13.8-40 39.7-40 69.3v96H64V128C64 57.3 121.3 0 192 0h64c70.7 0 128 57.3 128 128v96H336V128c0-29.6-16.1-55.5-40-69.3V224H248V48zM67.1 304l-18 48H398.9l-18-48H67.1zM22.1 287.1c7-18.7 24.9-31.1 44.9-31.1H380.9c20 0 37.9 12.4 44.9 31.1l19.2 51.3c1.9 5.1 2.9 10.5 2.9 16c0 20.4-13.5 37.7-32 43.5v90c0 13.3-10.7 24-24 24s-24-10.7-24-24V400H80v88c0 13.3-10.7 24-24 24s-24-10.7-24-24V398c-18.5-5.8-32-23.1-32-43.5c0-5.5 1-10.9 2.9-16l19.2-51.3z"/>
</symbol>
<symbol id="icon-eye" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"> <symbol id="icon-eye" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 34 KiB

+31
View File
@@ -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 Version20250930161953 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 disposition ADD synced_with_bus_pro_net TINYINT(1) NOT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE disposition DROP synced_with_bus_pro_net');
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Controller\Administrative\Disposition;
use App\Entity\Disposition;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class BusProNetSyncToggleController extends AbstractController
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
#[Route('/administrative/disposition/bpn-sync-toggle/{uuid}', name: 'app_administrative_disposition_bpn_sync_toggle', methods: ['POST'])]
#[IsGranted('ROLE_ADMINISTRATIVE')]
public function index(Disposition $disposition, Request $request): Response
{
$isSynced = $disposition->isSyncedWithBusProNet();
$disposition->setSyncedWithBusProNet(!$isSynced);
$this->entityManager->flush();
$this->addFlash('success', 'BusProNet Status aktualisiert');
$this->logger->info('Edit toggle BusProNet sync', [
'disposition' => $disposition->getUuid(),
'synced' => $disposition->isSyncedWithBusProNet(),
]);
return new HxRedirectResponse($this->generateUrl('app_administrative_assignment_detail', [
'uuid' => $disposition->getAssignment()->getUuid(),
]));
}
}
+15
View File
@@ -69,6 +69,9 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
#[ORM\Column(type: Types::TEXT, nullable: true)] #[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $calledOffReason = null; private ?string $calledOffReason = null;
#[ORM\Column(type: Types::BOOLEAN)]
private bool $syncedWithBusProNet = false;
public function __construct(Application $application) public function __construct(Application $application)
{ {
$this->uuid = Uuid::v4(); $this->uuid = Uuid::v4();
@@ -277,4 +280,16 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
return $this; return $this;
} }
public function isSyncedWithBusProNet(): bool
{
return $this->syncedWithBusProNet;
}
public function setSyncedWithBusProNet(bool $syncedWithBusProNet): static
{
$this->syncedWithBusProNet = $syncedWithBusProNet;
return $this;
}
} }
+4
View File
@@ -63,6 +63,10 @@ class AssignmentFilterType extends AbstractType
'label' => 'vergangene Einsätze anzeigen', 'label' => 'vergangene Einsätze anzeigen',
'required' => false, 'required' => false,
]) ])
->add('syncedWithBusProNet', CheckboxType::class, [
'label' => 'in BusProNet hinterlegt',
'required' => false,
])
->add('country', ChoiceType::class, [ ->add('country', ChoiceType::class, [
'label' => 'Land', 'label' => 'Land',
'required' => false, 'required' => false,
+13
View File
@@ -18,6 +18,7 @@ class AssignmentFilterDto extends AbstractFilterDto
protected array $status = []; protected array $status = [];
protected bool $includePast = false; protected bool $includePast = false;
protected ?string $country = null; protected ?string $country = null;
protected bool $syncedWithBusProNet = false;
public function getId(): ?int public function getId(): ?int
{ {
@@ -126,4 +127,16 @@ class AssignmentFilterDto extends AbstractFilterDto
return $this; return $this;
} }
public function isSyncedWithBusProNet(): bool
{
return $this->syncedWithBusProNet;
}
public function setSyncedWithBusProNet(bool $syncedWithBusProNet): static
{
$this->syncedWithBusProNet = $syncedWithBusProNet;
return $this;
}
} }
+7
View File
@@ -185,6 +185,13 @@ class AssignmentRepository extends ServiceEntityRepository
->setParameter('country', $country) ->setParameter('country', $country)
; ;
} }
if (true === $filterDto->isSyncedWithBusProNet()) {
$qb
->andWhere($qb->expr()->eq('disposition.syncedWithBusProNet', ':syncedWithBusProNet'))
->setParameter('syncedWithBusProNet', true)
;
}
} }
public function getBookmarkQueryForTeamer(Teamer $teamer): Query public function getBookmarkQueryForTeamer(Teamer $teamer): Query
@@ -51,6 +51,9 @@ class AssignmentFilterHandler extends AbstractFilterHandler
if (isset($data['country'])) { if (isset($data['country'])) {
$filterDto->setCountry($data['country']); $filterDto->setCountry($data['country']);
} }
if (isset($data['synced_with_bus_pro_net'])) {
$filterDto->setSyncedWithBusProNet((bool) $data['synced_with_bus_pro_net']);
}
return $filterDto; return $filterDto;
} }
@@ -70,6 +73,7 @@ class AssignmentFilterHandler extends AbstractFilterHandler
'status' => $filterDto->getStatus(), 'status' => $filterDto->getStatus(),
'include_past' => $filterDto->isIncludePast(), 'include_past' => $filterDto->isIncludePast(),
'country' => $filterDto->getCountry(), 'country' => $filterDto->getCountry(),
'synced_with_bus_pro_net' => $filterDto->isSyncedWithBusProNet(),
]); ]);
} }
} }
@@ -192,6 +192,9 @@
</td> </td>
<td> <td>
<div class="flex items-center justify-end space-x-2"> <div class="flex items-center justify-end space-x-2">
<button type="button" hx-post="{{ path('app_administrative_disposition_bpn_sync_toggle', { 'uuid': disposition.uuid }) }}" hx-swap="none">
{{ icon('chair', html_classes('w-5 h-5', {'text-green-500': disposition.syncedWithBusProNet })) }}
</button>
{% if is_granted('CONTRACT_SUPPLEMENTARY', disposition) %} {% if is_granted('CONTRACT_SUPPLEMENTARY', disposition) %}
<button type="button" <button type="button"
title="Dokumentenupload" title="Dokumentenupload"
@@ -19,7 +19,10 @@
{{ form_row(filterForm.hotels) }} {{ form_row(filterForm.hotels) }}
{{ form_row(filterForm.duration) }} {{ form_row(filterForm.duration) }}
{{ form_row(filterForm.country) }} {{ form_row(filterForm.country) }}
{{ form_row(filterForm.includePast) }} <div class="grid grid-cols-2 gap-x-4 gap-y-2">
{{ form_row(filterForm.includePast) }}
{{ form_row(filterForm.syncedWithBusProNet) }}
</div>
</div> </div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
{{ form_widget(filterForm.apply, { 'attr': { 'class': 'btn' } }) }} {{ form_widget(filterForm.apply, { 'attr': { 'class': 'btn' } }) }}