diff --git a/config/packages/chill_ticket.yaml b/config/packages/chill_ticket.yaml new file mode 100644 index 000000000..acb5571dc --- /dev/null +++ b/config/packages/chill_ticket.yaml @@ -0,0 +1,4 @@ +chill_ticket: + ticket: + person_per_ticket: one # One of "one"; "many" + diff --git a/src/Bundle/ChillTicketBundle/src/Action/Ticket/SetPersonsCommand.php b/src/Bundle/ChillTicketBundle/src/Action/Ticket/SetPersonsCommand.php index 69ba61977..aab0b968b 100644 --- a/src/Bundle/ChillTicketBundle/src/Action/Ticket/SetPersonsCommand.php +++ b/src/Bundle/ChillTicketBundle/src/Action/Ticket/SetPersonsCommand.php @@ -12,9 +12,11 @@ declare(strict_types=1); namespace Chill\TicketBundle\Action\Ticket; use Chill\PersonBundle\Entity\Person; +use Chill\TicketBundle\Validation\Validator\SetPersonCommandConstraint; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints\GreaterThan; +#[SetPersonCommandConstraint] class SetPersonsCommand { public function __construct( diff --git a/src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php b/src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php index c9886759c..0510c49cf 100644 --- a/src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php +++ b/src/Bundle/ChillTicketBundle/src/Controller/EditTicketController.php @@ -12,15 +12,21 @@ declare(strict_types=1); namespace Chill\TicketBundle\Controller; use Chill\TicketBundle\Entity\Ticket; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Twig\Environment; class EditTicketController { + private string $personPerTicket; + public function __construct( private readonly Environment $templating, - ) {} + ParameterBagInterface $parameterBag, + ) { + $this->personPerTicket = $parameterBag->get('chill_ticket')['ticket']['person_per_ticket']; + } #[Route('/{_locale}/ticket/ticket/{id}/edit', name: 'chill_ticket_ticket_edit')] public function __invoke( @@ -31,6 +37,7 @@ class EditTicketController '@ChillTicket/Ticket/edit.html.twig', [ 'ticket' => $ticket, + 'personPerTicket' => $this->personPerTicket, ] ) ); diff --git a/src/Bundle/ChillTicketBundle/src/DependencyInjection/ChillTicketExtension.php b/src/Bundle/ChillTicketBundle/src/DependencyInjection/ChillTicketExtension.php index f2222aa7a..596cb655a 100644 --- a/src/Bundle/ChillTicketBundle/src/DependencyInjection/ChillTicketExtension.php +++ b/src/Bundle/ChillTicketBundle/src/DependencyInjection/ChillTicketExtension.php @@ -24,6 +24,11 @@ class ChillTicketExtension extends Extension implements PrependExtensionInterfac { public function load(array $configs, ContainerBuilder $container) { + $configuration = $this->getConfiguration($configs, $container); + $config = $this->processConfiguration($configuration, $configs); + + $container->setParameter('chill_ticket', $config); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); $loader->load('services.yaml'); } diff --git a/src/Bundle/ChillTicketBundle/src/DependencyInjection/Configuration.php b/src/Bundle/ChillTicketBundle/src/DependencyInjection/Configuration.php new file mode 100644 index 000000000..19c107a09 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/DependencyInjection/Configuration.php @@ -0,0 +1,42 @@ +getRootNode(); + + /** @var ArrayNodeDefinition $ticketArray */ + $ticketArray = $rootNode + ->children() + ->arrayNode('ticket') + ->addDefaultsIfNotSet() + ; + + $ticketArray + ->children() + ->enumNode('person_per_ticket') + ->values(['one', 'many']) + ->defaultValue('many') + ->end(); + + return $treeBuilder; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts b/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts index 4a244e9a4..0b327fed9 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts @@ -111,7 +111,6 @@ export type EmergencyStateEvent = TicketHistory< >; export type CallerStateEvent = TicketHistory<"set_caller", CallerState>; -// TODO : Remove add_person event from TicketHistoryLine export type TicketHistoryLine = | AddPersonEvent | CreateTicketEvent @@ -125,11 +124,7 @@ export type TicketHistoryLine = interface BaseTicket { type_extended: T; -} - -export interface TicketSimple extends BaseTicket<"ticket_ticket:simple"> { type: "ticket_ticket"; - type_extended: "ticket_ticket:simple"; id: number; externalRef: string; currentAddressees: UserGroupOrUser[]; @@ -140,6 +135,10 @@ export interface TicketSimple extends BaseTicket<"ticket_ticket:simple"> { caller: Person | Thirdparty | null; } +export interface TicketSimple extends BaseTicket<"ticket_ticket:simple"> { + type_extended: "ticket_ticket:simple"; +} + export interface Ticket extends BaseTicket<"ticket_ticket:extended"> { type_extended: "ticket_ticket:extended"; createdAt: DateTime | null; diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/index.ts b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/index.ts index df1074496..03696e52a 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/index.ts +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/index.ts @@ -9,6 +9,7 @@ import { store } from "./store"; declare global { interface Window { initialTicket: string; + ticketPersonPerTicket: 'one'|'multi'; } } diff --git a/src/Bundle/ChillTicketBundle/src/Resources/views/Ticket/edit.html.twig b/src/Bundle/ChillTicketBundle/src/Resources/views/Ticket/edit.html.twig index 2b067304e..48e620a74 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/views/Ticket/edit.html.twig +++ b/src/Bundle/ChillTicketBundle/src/Resources/views/Ticket/edit.html.twig @@ -9,6 +9,7 @@ {{ parent() }} {{ encore_entry_script_tags('vue_ticket_app') }} {% endblock %} diff --git a/src/Bundle/ChillTicketBundle/src/Validation/Validator/SetPersonCommandConstraint.php b/src/Bundle/ChillTicketBundle/src/Validation/Validator/SetPersonCommandConstraint.php new file mode 100644 index 000000000..402a0d650 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Validation/Validator/SetPersonCommandConstraint.php @@ -0,0 +1,25 @@ +isMulti = 'multi' === $parameterBag->get('chill_ticket')['ticket']['person_per_ticket']; + } + + public function validate($value, Constraint $constraint) + { + if (!$value instanceof SetPersonsCommand) { + throw new UnexpectedValueException($value, SetPersonsCommand::class); + } + + if (!$constraint instanceof SetPersonCommandConstraint) { + throw new UnexpectedValueException($constraint, SetPersonCommandConstraint::class); + } + + if (!$this->isMulti) { + if (1 < count($value->persons)) { + $this->context->buildViolation($constraint->notMulti) + ->atPath('persons') + ->addViolation(); + } + } + } +} diff --git a/src/Bundle/ChillTicketBundle/src/config/services.yaml b/src/Bundle/ChillTicketBundle/src/config/services.yaml index e5618284a..7e3d6050b 100644 --- a/src/Bundle/ChillTicketBundle/src/config/services.yaml +++ b/src/Bundle/ChillTicketBundle/src/config/services.yaml @@ -23,5 +23,8 @@ services: Chill\TicketBundle\Menu\: resource: '../Menu/' + Chill\TicketBundle\Validation\: + resource: '../Validation/' + Chill\TicketBundle\DataFixtures\: resource: '../DataFixtures/' diff --git a/src/Bundle/ChillTicketBundle/tests/Validation/Validator/SetPersonCommandConstraintValidatorTest.php b/src/Bundle/ChillTicketBundle/tests/Validation/Validator/SetPersonCommandConstraintValidatorTest.php new file mode 100644 index 000000000..fd164354a --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Validation/Validator/SetPersonCommandConstraintValidatorTest.php @@ -0,0 +1,90 @@ + ['ticket' => ['person_per_ticket' => $this->personPerTicket]]]) + ); + } + + /** + * Helper method to set the configuration and recreate the validator. + */ + private function setPersonPerTicket(string $personPerTicket): void + { + $this->personPerTicket = $personPerTicket; + $this->validator = $this->createValidator(); + $this->validator->initialize($this->context); + } + + public function testValidatorWithManyPersonsPerTicket(): void + { + $this->setPersonPerTicket('multi'); + + $command = new SetPersonsCommand([new Person(), new Person()]); + + $this->validator->validate($command, new SetPersonCommandConstraint()); + + $this->assertNoViolation(); + } + + public function testValidatorWithSinglePersonPerTicket(): void + { + $this->setPersonPerTicket('single'); + + $command = new SetPersonsCommand([new Person(), new Person()]); + + $this->validator->validate($command, $command = new SetPersonCommandConstraint()); + + $this->buildViolation($command->notMulti)->atPath('property.path.persons')->assertRaised(); + } + + public function testValidatorWithSinglePersonPerTicketAndEmptyPersons(): void + { + $this->setPersonPerTicket('single'); + + $command = new SetPersonsCommand([]); + + $this->validator->validate($command, new SetPersonCommandConstraint()); + + $this->assertNoViolation(); + } + + public function testValidatorWithSinglePersonPerTicketAndOnlyOnePerson(): void + { + $this->setPersonPerTicket('single'); + + $command = new SetPersonsCommand([new Person()]); + + $this->validator->validate($command, new SetPersonCommandConstraint()); + + $this->assertNoViolation(); + } +}