WebBlocks Appointments

Requisitos

Versión del paquete documentado: 0.12.2. WebBlocks CMS ^1.73.0; PHP >=8.3.

A WebBlocks CMS Complemento que permite a un sitio aceptar reservas en su propio dominio, en lugar de vincular a los visitantes a un servicio de programación de terceros.

Instalar

Compile el artefacto y luego instálelo a través de System → Plugins en el administrador de CMS utilizando el flujo de carga ZIP normal.

composer plugin:build

El artefacto y su SHA-256 aterrizan bajo build/. Instalación de complementos deshabilitada; habilite el complemento explícitamente desde la pantalla de detalles del complemento después de revisarlo.

Convenciones

Todo lo que posee el complemento tiene un espacio de nombres según su identificador, según las reglas de convención del paquete de complementos CMS:

handle              webblocks-appointments
settings namespace  webblocks_appointments
database prefix     webblocks_appointments_
admin routes        /webadmin/plugins/webblocks-appointments
public routes       /plugins/webblocks-appointments
route names         webblocks.plugins.webblocks_appointments.*
permissions         webblocks-appointments.view, .manage, .settings

El formulario de reserva

Agregue el bloque Aformulario de cita a una página. Al elegir un servicio o día, se obtienen los horarios disponibles sin necesidad de recargar la página completa. Con JavaScript deshabilitado, el formulario GET generado por el servidor permanece disponible. Cada reserva se envía al servidor, que vuelve a comprobar la disponibilidad.

El título, la introducción y la etiqueta de envío se pueden traducir por ubicación de bloque. Sólo la copia del bloque es por bloque. Los servicios, el personal y los horarios de apertura afectan a todo el sitio, porque al duplicarlos por bloque es como dos páginas de reservas terminan discrepando silenciosamente sobre los horarios de apertura.

Dos protecciones que vale la pena conocer, porque ninguna es visible en el marcado:

  • Los espacios enviados se redirigen, no son confiables. El reservante impone conflictos, pero no las reglas que deciden lo que debería haberse ofrecido: horarios de apertura, plazos de entrega, horizonte. Sin la nueva verificación, una publicación diseñada podría reservarse a las 03:00 de un domingo cerrado, ya que nada de eso choca con una cita existente.
  • source_url solo se acepta como una ruta del mismo sitio. Una URL absoluta haría que el formulario fuera una redirección abierta.

Notificaciones

Cuando llega una reserva, la empresa recibe un anuncio y el visitante recibe una confirmación con la cita como un archivo adjunto .ics, lo que la coloca en su propio calendario sin cuenta, sin OAuth y sin servicio externo. La copia comercial establece al cliente como respuesta, por lo que se puede responder a una reserva respondiendo a ella; la dirección De sigue siendo el remitente configurado, porque falla el envío del visitante allí SPF.

Vale la pena conocer tres reglas:

  • La notificación ocurre después de que se confirma la reserva, nunca dentro de la transacción. Un envío que arroja no debe revertir un espacio al visitante que ya se le ha dicho que es suyo.
  • Las dos partes se intentan y registran de forma independiente. Un destinatario comercial mal escrito no debe suprimir la confirmación del visitante, y un estado combinado haría que la pantalla de administración se mostrara exactamente en el caso de que un operador lo necesite para ser honesto.
  • sent significa que el transporte lo aceptó, no que llegó. Los sobres publicitarios log, array y null se informan como no configurado en lugar de como enviados, porque reportarlos como enviados es una mentira que un operador no puede ver.

Se desinfectan los detalles del error almacenado: las cadenas de conexión y los secretos etiquetados se redactan y el mensaje se limita, porque se muestra a los operadores y una excepción SMTP sin formato lleva credenciales de forma rutinaria.

El destinatario comercial se resuelve desde la configuración del complemento, luego la dirección de contacto del sitio y luego el remitente configurado.

Recordatorios

Los recordatorios se envían mediante un comando Artisan, no una cola: el núcleo de CMS no envía trabajos en cola y la introducción de una dependencia de cola es una decisión fundamental que este complemento no tiene por qué tomar. Agréguelo al cron del host:

php artisan webblocks-appointments:dispatch-reminders

Cada pocos minutos está bien. Cada cita se considera exactamente una vez: el resultado se registra sea cual sea, por lo que una ejecución no cuesta nada cuando no hay nada adeudado, y una dirección inalcanzable no se vuelve a intentar en cada tic. --dry-run informa lo que saldría. El cliente potencial es por sitio y cero desactiva los recordatorios.

Cancelación de visitante

Los correos electrónicos de confirmación y recordatorio llevan un enlace de cancelación. No hay cuenta ni inicio de sesión: la cancel_token de la cita es la credencial, que es el único diseño viable en un CMS sin un sistema de usuario público.

Tres reglas lo mantienen seguro y honesto:

  • GET solo muestra una página de confirmación; DELETE cancela. Los clientes de correo, escáneres de enlaces y sistemas de seguridad corporativos siguen enlaces sin solicitud del usuario. Cancelar mediante GET permitiría que los filtros antispam cancelaran reservas.
  • Un token desconocido y una cita inexistente se muestran igual. Distinguirlos permitiría comprobar tokens adivinados.
  • Una cita que ya comenzó no se puede cancelar aquí. Permitirlo convertiría retroactivamente una inasistencia en una cancelación.

Cuando un visitante cancela, se notifica a la empresa y cancelled_by registra que fue el visitante en lugar de un operador. Si esa notificación falla, el visitante nunca la ve: su cancelación ya está confirmada y el resultado aún se registra para el operador.

Tiempo y corrección

Los instantes de las citas se almacenan en UTC. Los horarios de apertura y sus excepciones de fecha se almacenan como reloj de pared local, porque "abrimos a las 09:00" tiene que significar las 09:00 en ambos lados de una transición de horario de verano. El reloj del sitio proviene de Site::resolvedTimezone(), nunca de config('app.timezone').

El generador de tragamonedas recorre el tiempo del reloj de pared local para que las tragamonedas lleguen a las marcas que espera el visitante. De esto se derivan dos casos de transición, y ambos son deliberados:

  • Primavera adelante. Los tiempos del reloj de pared dentro del espacio no existen y no se ofrecen.
  • Fall back. Los tiempos del reloj de pared en la hora repetida existen dos veces; el generador elige el instante anterior. El valor predeterminado de PHP es el último, por lo que se trata de una elección explícita en lugar de un comportamiento heredado.

La doble reserva se evita de tres maneras: una transacción con una lectura de superposición de bloqueo (la protección real y la única que comprende los buffers y las diferentes duraciones), un índice único (resource_id, slot_lock) como respaldo de la base de datos que aún permite volver a reservar una ranura cancelada y la traducción de la violación de integridad resultante a una respuesta de ranura no disponible en lugar de un 500.

Pantallas del operador

Appointments muestra un día a la vez, en el reloj propio del sitio, con cambios de estado y entrada manual. Services, Staff & Rooms y Opening Hours definen qué se puede reservar y cuándo. Appointment settings mantiene las reglas de reserva, y son por sitio: dos sitios en una instalación no tienen que ponerse de acuerdo sobre el tiempo de entrega o el modo de confirmación.

A El servicio o recurso que ya tiene citas se desactiva en lugar de eliminarse, por lo que las reservas anteriores mantienen su historial y no se pueden realizar nuevas en su contra. La entrada manual pasa por el mismo reservador que el formulario público, por lo que no puede realizar una doble reserva, pero omite deliberadamente la nueva verificación de disponibilidad, porque un operador que reserva fuera del horario de apertura está tomando una decisión, no evadiendo una regla.

API y controles de estado

La API de token de portador expone servicios, personal y salas, disponibilidad semanal, excepciones de fecha, configuraciones y citas de solo lectura en /webadmin/api/plugins/webblocks-appointments. Descubra los puntos finales habilitados y las capacidades requeridas a través del descubrimiento de API de CMS y el esquema OpenAPI.

Plugin Configuración de la base de datos de comprobaciones de estado, servicios y recursos activos, asignaciones de servicios, horarios de apertura, destinatarios de notificaciones, correo saliente y programación de recordatorios.