Aller au contenu

Réservations et créneaux

Extension payante. Un formulaire peut proposer des créneaux de rendez-vous : horaires, capacité, liste d’attente et annulation par lien signé.

Ce document décrit ce que le module garantit et ce qu’il refuse. Le guide utilisateur en donne la version courte, dans la section « Prendre rendez-vous ».

Tout se décide dans le fuseau du site

Un créneau de neuf heures est à neuf heures pour celui qui reçoit. Le décider dans le fuseau du visiteur ferait apparaître des horaires d’ouverture différents selon le pays d’où l’on regarde, et un rendez-vous pris « à neuf heures » depuis Montréal tomberait à quatorze heures sur place.

Les instants sont rangés en UTC et réglés en heure locale. Ranger l’heure locale ferait qu’un créneau pris avant le changement d’heure et relu après désignerait un autre moment ; régler en UTC obligerait l’administrateur à recalculer ses horaires à chaque saison.

Le passage à l’heure d’été

Au printemps, une heure locale n’existe pas : on passe de deux heures à trois heures. PHP ramène l’heure manquante sur la suivante, et deux créneaux voisins désignent alors le même instant. Les créneaux sont donc dédoublonnés par instant — sans quoi le formulaire proposerait deux fois le même rendez-vous ce jour-là, avec deux capacités distinctes pour une seule plage réelle.

À l’automne, une heure locale existe deux fois. PHP en retient une, et l’autre n’est pas proposée : une heure de moins ce jour-là vaut mieux qu’un créneau dont personne — ni le client, ni celui qui reçoit — ne saurait dire auquel des deux passages il correspond.

La capacité est portée par un index

Une réservation confirmée occupe un siège numéroté, et UNIQUE (form_id, slot_start, seat) interdit que deux réservations occupent le même. Prendre une place est donc une insertion : elle réussit, ou elle échoue parce que la place est prise.

L’alternative — compter les réservations puis insérer si le compte le permet — laisse entre les deux une fenêtre où tout peut arriver. Deux clics simultanés sur la dernière place comptent tous deux « une place libre » et insèrent tous deux. Aucune relecture ne rattrape cela ; seule une contrainte le rend impossible.

Pourquoi pas de transaction explicite : elle n’apporterait rien, une seule écriture étant en jeu. Elle serait même trompeuse, puisque MyISAM — que certains hébergements imposent encore — l’accepte sans l’honorer. Mieux vaut une garantie que le moteur applique vraiment.

Le siège peut être nul

MySQL autorise plusieurs valeurs nulles dans un index unique. Une réservation annulée ou en liste d’attente porte donc un siège nul : elle n’occupe rien, et plusieurs peuvent coexister sur le même créneau.

C’est ce qui fait qu’une annulation libère réellement la place sans effacer la ligne : l’historique reste, le siège repart. Garder le siège sur une réservation annulée aurait immobilisé une place que plus personne n’occupe.

entry_id est unique : une soumission ne réserve qu’une fois, et un traitement rejoué ne prend pas une seconde place.

La disponibilité affichée n’est pas une promesse

Elle est lue au moment du rendu, et le créneau peut se remplir entre l’affichage et l’envoi. L’affichage sert à choisir, pas à garantir — et c’est pourquoi la place se prend par une insertion, non d’après le nombre affiché.

Un créneau plein disparaît de la liste, sauf si la liste d’attente est ouverte : proposer une place qu’on sait prise ferait remplir un formulaire pour rien.

Le nombre de places restantes n’est annoncé qu’au-delà de l’unité : « une place restante » sur un créneau à capacité un n’apprend rien, et répété sur toute la liste, cela ne fait que du bruit.

Le champ

Une liste déroulante groupée par jour, et pas un calendrier cliquable. Un sélecteur de dates maison demande d’écrire la navigation au clavier, les annonces de lecteur d’écran, le comportement tactile et la gestion du focus — c’est-à-dire tout ce qu’un select natif fait déjà, mieux, et dans la langue du système.

Les optgroup donnent la structure qu’un calendrier apporterait, sans en reprendre les problèmes.

Le champ ne calcule rien : les créneaux sont injectés dans sa configuration au rendu, par le filtre solis_forms_form_pages. Lui donner accès au calendrier et au dépôt l’aurait rendu impossible à rendre hors d’une requête complète, donc impossible à éprouver.

Le règlement d’abord, la place ensuite

La réservation a lieu après que le garde de paiement a refusé toute soumission dont la transaction n’est pas confirmée : un créneau n’est jamais pris sur un règlement en attente.

Elle consulte aussi solis_forms_pro_entry_effects_allowed : si le formulaire demande une confirmation d’adresse, la place attend que l’adresse soit confirmée. Une place tenue par une adresse que personne n’a prouvé posséder est une place perdue pour tout le monde.

L’annulation

Le lien est signé — même mécanisme que la confirmation d’adresse, dans un contexte distinct : présenter un lien de confirmation à la route d’annulation, ou l’inverse, ne donne rien même si les rangs coïncident. La base ne conserve qu’une empreinte.

Le lien redirige immédiatement, comme celui de confirmation : rendre une page à son adresse y laisserait le secret dans l’historique, la barre d’adresse, le journal d’accès et l’en-tête Referer.

Le délai d’annulation protège celui qui reçoit. Passé ce délai, le lien ne fonctionne plus : une annulation une heure avant un rendez-vous ne libère pas une place utilisable, et laisse surtout quelqu’un devant une plage vide qu’il avait réservée à son emploi du temps.

Réglez-le avec le délai de prévenance : un délai d’annulation de vingt-quatre heures et aucun délai de prévenance font que les premiers créneaux offerts sont déjà non annulables.

L’annulation administrative, elle, ne connaît pas de délai — c’est celui qui reçoit, ou son équipe, qui agit.

La liste d’attente

La promotion est manuelle. Une promotion automatique enverrait une confirmation à quelqu’un qui a peut-être pris un autre rendez-vous entre-temps, et personne ne serait là pour en juger — ni pour l’appeler.

L’adresse prévenue est désignée

Pas devinée. Prendre « le premier champ d’adresse » enverrait la confirmation à l’adresse d’un tiers sur un formulaire qui en porte deux — celle d’un accompagnant, d’un employeur.

Ce que le module ne fait pas

Ni synchronisation Google ou Outlook, ni ressources multiples, ni rendez-vous à deux sens, ni récurrence complexe, ni facturation fiscale.

Il ne tient pas non plus la place pendant un paiement en cours : deux personnes réglant en même temps la dernière place verront l’une d’elles placée en liste d’attente, ou refusée si l’attente n’est pas ouverte. Tenir une place demande de décider quand la relâcher, et une place immobilisée par un panier abandonné est une place perdue tant que ce délai n’est pas écoulé.