Faciliter la prise de rendez-vous en ligne grâce au composant Workflow de Symfony
Publié le 09 février 2024
Rustine Libre est une toute nouvelle plateforme facilitant la mise en relation entre des cyclistes et des réparateurs de vélo. Le collectif à l’initiative de cette application porte les valeurs de l’économie sociale et solidaire, et a souhaité les retranscrire dans ce projet. Par exemple, la liste des réparateurs s’actualise de façon aléatoire, dans un souci de ne pas mettre en avant un réparateur plus qu’un autre. Les-Tilleuls.coop est intervenue sur le développement back-end, le développement front-end ainsi que sur l’UX/UI design et le pilotage du projet. Dans cet article, nous allons voir plus en détail comment fonctionne, "sous le capot", le processus de réservation d’un créneau de réparation de vélo.
Quels besoins pour la prise de rendez-vous ?
Lorsqu’un cycliste souhaite rencontrer un réparateur, il a la possibilité de choisir un créneau horaire proposé par celui-ci. Le processus d’un rendez-vous avec le professionnel passe par plusieurs états :
- En attente de validation par le réparateur (il s’agit de l’état initial lorsqu’un cycliste prend rendez-vous).
- Rendez-vous validé par le réparateur.
- Rendez-vous annulé.
- Rendez-vous refusé.
Dans ce processus, on souhaite aussi ajouter des règles permettant par exemple de :
- Pouvoir valider un rendez-vous seulement s’il est en attente de validation par le réparateur. On ne pourra alors pas valider un rendez-vous s’il est déjà refusé.
- Ne pas pouvoir refuser un rendez-vous si celui-ci a déjà été annulé.
- Etc…
Voici une brève représentation de la logique métier qu’on souhaite mettre en place :
La solution mise en place
Le titre de notre article était déjà évocateur, nous avons choisi d’utiliser le composant Workflow de Symfony, ajouté depuis la version 3.2 du framework. Ce composant permet de réguler le flux de travail d’un objet, en définissant plusieurs états (appelés “places”) et des “transitions” permettant d’autoriser ou non de passer d’un état à un autre. L’ensemble de nos états et transitions sont des “définitions”.
Dans notre cas, voici la configuration que nous avons définie :
framework:
workflows:
appointment_acceptance:
type: 'state_machine'
audit_trail:
enabled: true
marking_store:
type: method
property: status
supports:
- App\Entity\Appointment
initial_marking: pending_repairer
places:
- pending_repairer # en attente de validation
- validated # validé
- refused # refusé
- cancel # annulé
transitions:
validated_by_repairer:
from: pending_repairer
to: validated
refused:
from: pending_repairer
to: refused
propose_another_slot:
from: [pending_repairer, validated]
to: validated
cancellation:
from: [pending_repairer, validated]
to: cancel
En regardant cette configuration, on peut noter que la définition s’appelle appointment_acceptance
et se base sur la propriété status
de l’entité Appointment
. Un rendez-vous se trouve dans l’un des quatre états suivants : pending_repairer
, validated
, refused
ou cancel
.
Ce sont les transitions définies ci-dessus qui autorisent ou non le passage d’un état à un autre.Chaque transition accepte un ou plusieurs états de départ et un seul état cible. On peut alors noter que :
- On ne peut valider un rendez-vous que s’il est en attente de validation.
- On ne peut refuser un rendez-vous que s’il est en attente de validation.
- On ne peut proposer un nouveau créneau horaire que si le rendez-vous est en attente de validation ou s’il est déjà validé.
- On ne peut annuler un rendez-vous que s’il est en attente de validation ou s’il est déjà validé.
Dans le cadre de notre projet, nous vérifions si la transition est autorisée avec la méthode ->can()
du Symfony\Component\Workflow\WorkflowInterface
. Si c’est le cas, la méthode ->apply()
permet de modifier notre objet.
<?php
#[AsController]
final class AppointmentStatusAction
{
public function __construct(
private readonly WorkflowInterface $appointmentAcceptanceStateMachine
){}
public function __invoke(Appointment $appointment, Request $request): Appointment
{
$content = $request->toArray();
if (!array_key_exists('transition', $content)) {
throw new BadRequestHttpException('...');
}
if (!$this->appointmentAcceptanceStateMachine->can($appointment, $content['transition'])) {
throw new BadRequestHttpException('...');
}
$this->appointmentAcceptanceStateMachine->apply($appointment, $content['transition']);
return $appointment;
}
}
En seulement quelques lignes de code et de configuration, le composant Workflow nous permet ainsi de gérer facilement le processus de prise de rendez-vous correspondant aux besoins métier. Si vous êtes cycliste, n’hésitez pas à aller faire un tour sur l’application Rustine Libre ! Dites-nous ce que vous en pensez et n’hésitez pas à nous contacter pour la réalisation de vos solutions sur mesure. Notre équipe se fera un plaisir de vous accompagner dans l’accomplissement de vos besoins.