Ao vivo · status OK
Documentação · OW Agenda v1.3.1

OW Agenda
Documentação

A marcação de consultas no WordPress que não deixa ninguém ocupar os teus horários em vão.

v1.3.1GPL-2.0-or-laterDocumentação

OW Agenda — Documentação

A marcação de consultas online e a agenda do dia a dia, dentro do WordPress, sem subscrição. Autor: OptionWeb — Julien Daniel Página do plugin: https://optionweb.dev/pt/addons/ow-agenda/ Licença: GPL-2.0-or-later Versão coberta por este documento: 1.3.1


Índice

  1. Visão geral
  2. Instalação
  3. Início rápido
  4. O percurso de reserva
  5. A dupla verificação por email
  6. A validação dos pedidos
  7. A página Agenda
  8. O diretório de clientes
  9. Os convites de sessão
  10. Emails e ficheiro de calendário (ICS)
  11. Lembretes e tarefa agendada
  12. Anti-spam e limites de débito
  13. RGPD
  14. Shortcodes
  15. API REST
  16. Referência das definições
  17. Dados armazenados
  18. Internacionalização
  19. Desinstalação
  20. Resolução de problemas
  21. FAQ
  22. Changelog

Visão geral

O OW Agenda acrescenta ao WordPress um sistema completo de marcações: uma página pública onde o visitante escolhe o dia e depois a hora, e uma página «Agenda» protegida por autenticação, pensada para ser usada a partir de um telemóvel, onde o utilizador gere o dia.

Tudo cabe dentro do site. Nenhum serviço externo, nenhuma API de terceiros, nenhuma subscrição: os horários são calculados pelo seu servidor, as marcações vivem nas suas tabelas MySQL, os emails saem por wp_mail().

O que é entregue (tudo gratuito, GPL-2):

  • Reserva online: escolha do dia, escolha do horário, formulário curto, caixa de consentimento RGPD
  • Duplo opt-in por email: um pedido só se torna real depois de clicado um link de validação — os bots nunca chegam à agenda
  • Validação manual (recomendada) ou confirmação automática, com botões Confirmar / Recusar diretamente no email de notificação (links assinados HMAC, sem necessidade de sessão iniciada)
  • Página «Agenda» mobile-first: vista do dia, pedidos pendentes, marcações telefónicas introduzidas à mão, bloqueio de horários, reagendamento, estados feito / faltou
  • Diretório de clientes: pesquisa, criação, edição, eliminação; alimentado automaticamente pelas marcações validadas
  • Convites de sessão: um link privado permite a um cliente existente escolher a data da sua sessão, num serviço e numa duração definidos por si
  • Emails HTML cuidados com anexo ICS (adição ao calendário do telemóvel num gesto), lembrete automático na véspera, anulação online pelo cliente
  • Anonimização automática das marcações passadas, purga dos pedidos nunca validados
  • API REST completa sob o namespace owag/v1

O que ele não faz, deliberadamente:

  • Sem pagamento online: o OW Agenda marca a consulta, não cobra um sinal (use o WooCommerce se for essa a sua necessidade)
  • Uma única agenda: sem gestão multiprofissional nem multirrecurso; o plugin descreve um planeamento, o do site
  • Sem sincronização bidirecional com o Google Calendar ou o Outlook: o calendário do cliente é atualizado por ficheiro ICS (sentido único), as suas indisponibilidades pessoais introduzem-se como bloqueios
  • Sem catálogo de serviços do lado do visitante: a reserva pública incide sobre um único serviço (designação e duração configuráveis); os restantes serviços passam pelos convites de sessão
  • Sem marcações recorrentes, sem videoconferência, sem sala de espera

Esta lista é uma escolha de arquitetura, não uma roadmap disfarçada: uma agenda simples que nunca se engana no horário vale mais do que uma máquina complicada em que ninguém se atreve a tocar.


Instalação

A partir do .zip

  1. Descarregue ow-agenda-1.3.1.zip de https://optionweb.dev/pt/addons/ow-agenda/
  2. Plugins → Adicionar novo → Carregar plugin
  3. Escolha o ficheiro, clique em Instalar, depois em Ativar

Por FTP

Descompacte o arquivo e coloque a pasta ow-agenda em /wp-content/plugins/, depois ative o plugin em Plugins.

Requisitos

  • WordPress 6.3 ou posterior
  • PHP 7.4 ou posterior (8.1+ recomendado)
  • MySQL 5.7+ / MariaDB 10.2+ — as funções GET_LOCK() / RELEASE_LOCK() são usadas para serializar as reservas simultâneas
  • Um envio de emails que funcione. É a única dependência real do plugin: todo o percurso (validação, confirmação, lembrete, anulação) passa pelo email. Num alojamento partilhado, instale um plugin SMTP antes de colocar a agenda online.

O que é instalado

Na ativação, o OW Agenda cria três tabelas:

TabelaConteúdo
{prefix}_owag_appointmentsTodos os eventos da agenda: consultas web, sessões resultantes de um convite, marcações introduzidas à mão, bloqueios de horários
{prefix}_owag_invitesOs links privados «escolha a data da sua sessão»
{prefix}_owag_customersO diretório de clientes

…e, apenas na primeira vez, duas páginas publicadas:

  • «Marcar uma consulta» — contém o shortcode [ow_agenda]
  • «Agenda» — contém o shortcode [ow_agenda_admin]

Os respetivos identificadores ficam guardados nas opções owag_page_booking e owag_page_admin; a flag owag_pages_created garante que uma desativação seguida de reativação não recria duplicados. Pode renomear estas páginas, colocá-las num menu, mudar a sua permalink: o plugin segue-as pelo ID.

A ativação acrescenta também:

  • a capacidade owag_manage ao papel administrador — é ela, e não manage_options, que abre a agenda e as rotas REST de administração;
  • as definições por defeito na opção owag_settings;
  • a tarefa agendada horária owag_hourly_event (primeira execução 5 minutos depois da ativação).

Um segredo HMAC (owag_admin_secret, 64 caracteres, sem carregamento automático) é gerado na primeira notificação de administração: é ele que assina os botões Confirmar / Recusar dos emails.

Dar acesso a outra pessoa

A página Agenda é visível para qualquer utilizador com sessão iniciada que disponha de owag_manage. Para abrir a agenda a uma assistente sem lhe dar as chaves do site:

// À exécuter une fois (mu-plugin, ou plugin de gestion des rôles).
$role = get_role( 'editor' );
if ( $role ) { $role->add_cap( 'owag_manage' ); }

Início rápido

Depois da ativação, vá a OW Agenda (menu principal da administração). O ecrã de definições cabe numa página; cinco minutos são suficientes.

1. O horário de funcionamento

Para cada dia da semana, indique um período (09:00 → 18:00) e, se fechar à hora de almoço, um segundo período (14:00 → 18:30). Um dia deixado vazio é um dia fechado. Por defeito: de segunda a sexta, 09:00–18:00; sábado e domingo fechados.

Os horários são interpretados no fuso do site (Definições → Geral → Fuso horário). Verifique-o antes de abrir as reservas: todas as datas são armazenadas em hora local.

2. O serviço reservável online

  • Designação da consulta — o que o visitante vê como título do widget («Consulta», «Primeira consulta», «Avaliação»…)
  • Duração da consulta — 60 minutos por defeito. É esta duração que fica bloqueada na agenda.
  • Granularidade dos horários — o intervalo entre duas horas propostas (30 minutos por defeito). Com uma duração de 60 e uma granularidade de 30, propõe 9:00, 9:30, 10:00… e a primeira marcação feita às 9:30 elimina as 9:00 e as 10:00 da lista.
  • Intervalo entre duas marcações — minutos de respiração acrescentados de um lado e do outro de cada horário candidato (0 por defeito).

3. Os prazos

  • Antecedência mínima de reserva — 24 h por defeito: um visitante não pode marcar para daqui a uma hora.
  • Horizonte de marcação — 60 dias por defeito: para além disso, nada mais é proposto.
  • Anulação online pelo cliente — até 24 h antes da marcação; passado esse prazo, a página de anulação convida-o a telefonar.

4. A validação e os emails

  • Confirmação dos pedidos: validação manual (recomendado) ou confirmação automática.
  • Dupla verificação por email: deixe a caixa assinalada. É a melhor proteção anti-bot do plugin.
  • Notificações de administração enviadas para: o seu endereço. Por defeito, o email de administração do site.

Guarde e abra a página «Marcar uma consulta»: o widget mostra os próximos 14 dias e os seus horários livres. Está online.

5. A agenda no telemóvel

Abra a página «Agenda» no seu telemóvel, inicie sessão e use «Adicionar ao ecrã principal». O plugin publica um manifesto de aplicação: a página abre então em ecrã inteiro, sem barra do navegador, como uma aplicação.


O percurso de reserva

Do lado do visitante, a página de reserva é um componente autónomo (JavaScript sem framework, menos de 10 KB) que fala com os endpoints públicos owag/v1/public/*.

Etapa 1 — o dia

Ao carregar, o widget pede as disponibilidades de 14 dias a partir de hoje e mostra uma faixa de dias clicáveis. Um dia sem horário livre fica cinzento e não é clicável. O botão «Ver as datas seguintes» carrega os 14 dias seguintes, tantas vezes quantas as necessárias até ao horizonte configurado.

As datas do widget são construídas em hora local do navegador, nunca em UTC. É uma correção da 1.3.0: antes, um visitante situado a leste de UTC que abrisse a página pouco depois da meia-noite via a lista começar na véspera e perdia um dia de disponibilidade.

Etapa 2 — a hora

O clique num dia chama /public/slots e mostra as horas de início livres. Um horário só é proposto quando todas estas condições estão reunidas:

  1. cai dentro de um período de abertura do dia em causa;
  2. a marcação inteira (início + duração) cabe antes do fecho;
  3. começa depois de agora + antecedência mínima;
  4. o dia está dentro do horizonte de marcação;
  5. não se sobrepõe a nenhum evento ativo, intervalo incluído — e «evento ativo» inclui as marcações confirmadas, os pedidos pendentes, os bloqueios, as marcações telefónicas introduzidas à mão e os pedidos ainda não verificados que continuam a reter o seu horário.

É este o ponto importante: tudo o que ocupa a agenda fecha o horário online. Uma marcação feita ao telefone e registada na agenda desaparece imediatamente dos horários propostos no site.

Etapa 3 — o formulário

Quatro campos, três deles obrigatórios: nome (2 caracteres no mínimo), telefone (8 dígitos no mínimo), email (validado), mensagem livre. Uma caixa de consentimento RGPD, não assinalada por defeito, é obrigatória.

O formulário transporta ainda dois campos invisíveis para o visitante — uma armadilha para robôs e um carimbo temporal de abertura da página — descritos na secção Anti-spam.

Etapa 4 — a resposta

Consoante a sua configuração, três desfechos:

ConfiguraçãoEstado criadoMensagem apresentada
Dupla verificação por email ativa (por defeito)unverified«Falta um último gesto: acabámos de lhe enviar um email…»
Verificação desativada + validação manualpending«O seu pedido foi bem recebido!»
Verificação desativada + confirmação automáticaconfirmed«A sua marcação está confirmada!»

Se o horário tiver sido ocupado entre a apresentação da lista e o envio do formulário, o visitante recebe uma mensagem explícita (owag_slot_taken, HTTP 409) e a lista dos dias recarrega automaticamente. Dois visitantes não podem obter o mesmo horário: a secção crítica é serializada por um bloqueio nomeado MySQL, próprio da sua base de dados e do seu prefixo de tabelas, o que se aguenta mesmo num alojamento partilhado.


A dupla verificação por email

É a funcionalidade que distingue o OW Agenda de um formulário de contacto disfarçado.

Quando a Dupla verificação por email está ativa (definição email_verify, ativa por defeito):

  1. O pedido é registado com o estado unverified. O administrador não é notificado. A marcação não aparece como um pedido a tratar.
  2. O visitante recebe um email «Falta um último gesto…» com um botão de validação.
  3. O horário fica retido durante 45 minutos. Passado esse prazo sem validação, volta a ficar disponível para toda a gente — um bot não pode, portanto, congelar o seu dia.
  4. O clique no botão abre uma página autónoma (?owag_verify=<uid>) que mostra o resumo da marcação e um botão «Confirmo o meu pedido». A validação só parte com o clique: os antivírus e os scanners de links que visitam os URL dos emails não validam nada.
  5. O pedido passa então a pending (validação manual) ou a confirmed (confirmação automática), o cliente recebe o email correspondente e é só nessa altura que sai a notificação de administração.
  6. Os pedidos nunca validados são eliminados ao fim de 48 h pela tarefa horária. Não deixam qualquer rasto nem qualquer dado pessoal.

Se, entre o envio e o clique, o horário tiver sido ocupado por outra pessoa (a janela de 45 minutos passou), a validação devolve um erro claro e o pedido é anulado — nunca uma marcação fantasma sobre um horário já ocupado.

Consequência prática: um endereço de email inválido não produz qualquer marcação. Deixa de perder tempo a ligar para números falsos. O preço a pagar é um clique adicional para o cliente; a experiência mostra que a taxa de abandono é muito inferior à taxa de marcações falsas que evita.

As reservas resultantes de um convite de sessão saltam esta etapa: o cliente já provou que lê a sua caixa de correio ao clicar no link privado que recebeu.


A validação dos pedidos

Validação manual (recomendada)

Definição por defeito: auto_confirm = 0. Um pedido verificado chega com o estado pending. Nada é prometido ao cliente enquanto não fizer nada — mas o horário já está bloqueado, ninguém lho pode roubar.

Recebe um email «A confirmar: » com o resumo completo (serviço, data, nome, telefone, email, mensagem do cliente) e dois botões:

  • Confirmar a marcação — ciano
  • Recusar — contorno vermelho

Os botões do email: links assinados HMAC

Estes botões não exigem qualquer sessão iniciada. Apontam para o seu site com três parâmetros: owag_admin_action (confirm ou refuse), uid (o identificador aleatório da marcação) e sig, uma assinatura HMAC-SHA256 de uid|action calculada com o segredo privado do site (owag_admin_secret).

  • A assinatura é verificada antes de qualquer detalhe ser apresentado: um link adulterado não mostra mais nada além de «Link inválido».
  • A comparação usa hash_equals() — sem fuga de informação pelo tempo de resposta.
  • A página mostra um resumo e um botão; a ação só é executada com o clique. Um scanner de links não confirma, portanto, nada em seu lugar.
  • Um pedido já tratado devolve «Já tratado (estado: … )» em vez de um erro.

Confirmar envia automaticamente o email de confirmação ao cliente, com o ficheiro de calendário. Recusar envia o email de anulação. Em ambos os casos, a agenda está atualizada antes de guardar o telemóvel.

Estes links continuam válidos enquanto a marcação estiver pendente. Se eliminar a opção owag_admin_secret (restauro parcial da base de dados, limpeza manual), todos os links já enviados deixam de funcionar: é gerado um novo segredo e as assinaturas antigas deixam de corresponder. Passe então pela página Agenda.

Confirmação automática

Definição auto_confirm = 1. Um horário livre é confirmado imediatamente: o cliente recebe a sua confirmação com o ficheiro de calendário, o utilizador recebe uma notificação «Nova marcação». A reservar para as atividades em que qualquer horário aberto é um horário aceitável.

As duas definições combinam-se com a dupla verificação: mesmo em confirmação automática, o pedido passa primeiro por unverified se email_verify estiver ativa.


A página Agenda

A página «Agenda» ([ow_agenda_admin]) é a ferramenta de todos os dias. Foi concebida para o telemóvel em primeiro lugar: botões largos, uma coluna, sem tabelas para percorrer horizontalmente, e funciona evidentemente igual de bem num ecrã de computador.

Está protegida: um visitante sem sessão iniciada vê um link de início de sessão, um utilizador com sessão iniciada mas sem a capacidade owag_manage vê «O acesso é reservado à equipa». A página está em noindex,nofollow: nunca irá parar ao Google.

Separador Agenda — a vista do dia

O dia em curso, evento a evento, com a hora, a duração, a designação, o estado e a origem (site, convite, introdução manual). Navegação de um dia para o outro, botão Hoje. Em cada marcação:

  • Detalhes — contactos do cliente, mensagem deixada durante a reserva, e um bloco de notas internas (nunca visíveis para o cliente) guardadas sem enviar qualquer email
  • Confirmar ✓ — para um pedido ainda pendente; o email de confirmação parte
  • Feito / Faltou (no-show) — estados de fim de marcação
  • Remarcar — nova data, nova hora, duração eventualmente alterada. O plugin pergunta-lhe se o cliente deve ser avisado por email; se sim, ele recebe uma confirmação atualizada e um ficheiro de calendário que corrige o evento já presente no seu telemóvel
  • Anular a marcação — com, também aqui, a opção de avisar ou não o cliente
  • Eliminar o bloqueio — para um horário bloqueado

Quando uma ação cria uma sobreposição (remarcação para um horário ocupado), o plugin avisa e pede confirmação: pode forçar. É o seu planeamento, sabe o que está a fazer — a salvaguarda só é bloqueante para os visitantes.

Adicionar uma marcação ou um bloqueio

O botão «Adicionar uma marcação» abre uma ficha única que serve dois usos:

  • Marcação — o cliente ligou-lhe. Nome, telefone, email (facultativo), serviço, data, hora, duração, notas internas. Se preencher um endereço de email e assinalar a opção, o cliente recebe a confirmação com o seu ficheiro de calendário, como se tivesse reservado online. A marcação alimenta também o diretório de clientes.
  • Bloqueio (férias, pausa…) — um motivo, uma data, uma hora, uma duração. Nenhum email, nenhuma ficha de cliente, mas o horário desaparece imediatamente da reserva online. É assim que se marca uma semana de férias, uma formação, ou o horário de almoço que não se quer ver ocupado.

Separador Pendentes

A lista dos pedidos verificados que aguardam a sua decisão, de todos os dias (as marcações já passadas ficam excluídas). Dois botões por linha: Confirmar e Recusar. É o primeiro ecrã a abrir de manhã.

Dica: a agenda como aplicação

Na página Agenda, o plugin declara um manifesto de aplicação web (?owag_manifest=1) com o nome do site, o ícone do site e a cor do tema. Tanto no Android como no iOS, o menu do navegador propõe então «Adicionar ao ecrã principal»: obtém um ícone, um arranque em ecrã inteiro e nunca mais um URL para escrever.


O diretório de clientes

O terceiro separador da página Agenda é um diretório leve, deliberadamente mínimo: nome, telefone, email, notas livres.

  • Preenche-se sozinho. Assim que uma marcação é validada (reserva online verificada, sessão por convite, introdução manual), o cliente é associado a uma ficha existente pelo seu email e depois pelo seu telefone. Se não existir, a ficha é criada; se existir, só os campos vazios são completados — o plugin nunca substitui aquilo que introduziu à mão.
  • Pesquisa pelo nome, pelo telefone ou pelo email (200 fichas apresentadas no máximo).
  • Criação e edição manuais, com um campo de notas para o histórico, as preferências, as precauções a tomar.
  • Dois atalhos por ficha: Nova marcação (pré-preenche a ficha de introdução manual) e Convidar para uma sessão (pré-preenche o convite).
  • Eliminação de uma ficha: as marcações passadas permanecem na agenda, apenas a ficha do diretório desaparece.

Este diretório não é um CRM nem pretende sê-lo. Responde a uma pergunta: «Quem é, já agora, a senhora das 14 h?»


Os convites de sessão

O caso de uso: um cliente existente tem direito a uma sessão — um acompanhamento, um retoque, um serviço vendido noutro contexto — e quer que ele escolha a data sem passar pela reserva pública, num serviço e numa duração que define.

A partir do separador Convites:

  1. Indique o nome do cliente, a designação da sessão (obrigatórios), a sua duração (15 a 720 minutos) e, se quiser, o seu email e o seu telefone.
  2. Escolha a validade do link: 60 dias por defeito, de 1 a 365.
  3. Assinale eventualmente «Enviar o link ao cliente por email» — o cliente recebe um email «Escolha a data da sua sessão» com a designação, a duração, a data de expiração e um botão.
  4. Caso contrário, copie o link e envie-o por SMS, WhatsApp, ou pelo botão de partilha nativo do telemóvel.

O link aponta para a sua página de reserva com um token privado (?owag_invite=<token>, 32 caracteres hexadecimais gerados por um gerador criptográfico). O widget mostra então a designação e a duração da sessão, e não a consulta padrão. O cliente preenche o mesmo formulário curto.

Regras que governam um link de convite:

  • Uso único. Depois de a sessão ser reservada, o link responde «Este link já foi utilizado» (HTTP 410). Duas aberturas simultâneas com o mesmo token não podem criar duas sessões: o consumo do token faz-se sob o mesmo bloqueio que a reserva do horário.
  • Datado. Passada a expiração, o link convida a contactá-lo novamente (HTTP 410).
  • Sem duplo opt-in. O cliente já recebeu este link por um canal que domina: a sessão é criada diretamente como confirmed, com confirmação e ficheiro de calendário.
  • Reciclado em caso de anulação. Se a sessão for anulada (por si ou pelo cliente), o convite é libertado: o link volta a ficar ativo e o convite reaparece na lista dos convites abertos. É uma correção da 1.3.0 — antes, uma anulação matava definitivamente o link e era preciso fazer outro.
  • Revogável. Eliminar um convite a partir da lista desativa o link imediatamente.

Emails e ficheiro de calendário (ICS)

Os emails transacionais

Todas as mensagens são em HTML, com uma composição em tabelas compatível com o Gmail e o Outlook: cartão branco sobre fundo claro, nome do site no cabeçalho, caixa de resumo com filete ciano, botões em pílula. São enviados por wp_mail(), pelo que respeitam a sua configuração SMTP e os filtros habituais do WordPress.

EmailDestinatárioDesencadeador
Validação do pedidoClienteReserva web quando a dupla verificação está ativa
Pedido recebidoClientePedido validado, a aguardar a sua decisão
Marcação confirmadaClienteConfirmação (manual, automática, introdução admin, remarcação) — com anexo ICS
Marcação anuladaClienteAnulação pelo cliente, recusa ou anulação pelo admin — com anexo ICS de cancelamento
LembreteClienteAutomaticamente, entre 12 e 36 h antes da marcação
Escolha a data da sua sessãoClienteCriação de um convite com envio por email
A confirmar: …AdminNovo pedido verificado pendente — com os botões Confirmar / Recusar
Nova marcação: …AdminNova marcação confirmada (confirmação automática, convite)
Anulação do cliente: …AdminO cliente anulou por si próprio a partir do seu email

O endereço de notificação de administração é a definição notify_email (por defeito o email de administração do site). Os emails para o cliente só saem se o endereço for válido, e nunca para um bloqueio de horário.

Os emails de confirmação e de anulação lembram ao cliente que pode anular online, com o número de horas de aviso prévio efetivamente configurado.

O anexo ICS

O ficheiro .ics anexado às confirmações é o que transforma um email numa marcação realmente presente no telemóvel do cliente: um gesto sobre o anexo, e o evento fica no seu calendário, com o seu próprio alerta.

O ficheiro está conforme a RFC 5545 e contém o necessário para que os clientes de calendário (Google, Outlook, Apple) tratem corretamente as atualizações:

  • METHOD:REQUEST na criação e em cada revisão de horário, METHOD:CANCEL na anulação;
  • um UID estável derivado do identificador da marcação e do domínio do site — é ele que permite a uma revisão substituir o evento existente em vez de criar um segundo;
  • um SEQUENCE crescente derivado da data da última modificação, reduzida a um instante absoluto: a passagem à hora de inverno não pode fazer recuar o número de revisão (e a anulação acrescenta 1, para se manter superior a uma revisão ocorrida no mesmo segundo);
  • ORGANIZER (o seu endereço de notificação) e ATTENDEE (o cliente);
  • DTSTART / DTEND em UTC, STATUS:CONFIRMED ou STATUS:CANCELLED;
  • dobragem das linhas a 75 bytes sem nunca cortar um caractere UTF-8.

Uma remarcação de uma consulta confirmada envia, portanto, um novo ficheiro que corrige o evento já presente no cliente; uma anulação envia um ficheiro que o elimina. É uma correção da 1.3.0: antes, o horário antigo ficava no calendário do cliente.

O ficheiro é escrito no diretório temporário do servidor — nunca em wp-content/uploads/, que é servido publicamente — através da API de ficheiros do WordPress, e é apagado logo que o envio termina, incluindo se o envio falhar. Contém o nome e o email do cliente: não tem nada que fazer no disco um segundo a mais do que o necessário.


Lembretes e tarefa agendada

Uma única tarefa agendada, owag_hourly_event, executada de hora a hora. Faz três coisas.

1. O lembrete da véspera

O lembrete parte quando a marcação começa dentro de 12 a 36 horas. Não é uma janela horária fixa, e isso é deliberado: o WP-Cron só é despoletado na visita a uma página. Um site sem tráfego à noite perdia definitivamente os lembretes do dia seguinte. Com uma janela deslizante, o lembrete parte na primeira execução disponível e recupera o atraso.

Condições: marcação confirmada, endereço de email preenchido, não ser um bloqueio, e o lembrete não ter já sido enviado.

Cada lembrete é reservado de forma atómica antes do envio (um UPDATE condicional sobre a flag reminder_sent): duas execuções de cron que se sobreponham não podem enviar duas vezes a mesma mensagem. Se o envio falhar, a reserva é devolvida e o lembrete será tentado de novo na execução seguinte. Um bloqueio curto (10 minutos) evita ainda que duas passagens simultâneas percorram a mesma lista.

Remarcar uma consulta repõe a flag a zero: o cliente recebe efetivamente um lembrete para o novo horário.

2. A purga dos pedidos não validados

Os pedidos que permanecem unverified há mais de 48 horas são eliminados. (O seu horário, esse, já tinha sido devolvido à disponibilidade ao fim de 45 minutos.)

3. A anonimização RGPD

Ver a secção RGPD.

A rede de segurança

Um evento WP-Cron pode desaparecer: otimização da base de dados, restauro parcial, plugin de limpeza, reinicialização da opção cron. O OW Agenda verifica a cada carregamento se a tarefa está bem agendada e reagenda-a caso contrário. Lembretes, purga e retenção não podem parar em silêncio.

Usar um verdadeiro cron de sistema

O WP-Cron depende do tráfego. Num site pouco visitado, prefira um cron de sistema:

// wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab -e — toutes les 15 minutes
*/15 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null

Anti-spam e limites de débito

A reserva é pública por natureza: sem conta, sem sessão iniciada, sem nonce possível. Cinco proteções independentes trabalham, por isso, a montante.

1. A armadilha para robôs (honeypot)

O formulário contém um campo de texto fora do ecrã, invisível para um humano e apetecível para um robô. O campo tem de estar presente e vazio. Um campo preenchido — ou ausente, o que denuncia um envio direto à API — devolve uma recusa seca (HTTP 403), sem detalhe explorável.

2. O tempo de preenchimento

A página transmite o carimbo temporal da sua apresentação. Um envio que chegue menos de 4 segundos depois do carregamento é recusado. Também aqui, um carimbo temporal ausente ou malformado é uma recusa: na 1.3.0, estes dois campos tornaram-se obrigatórios — omiti-los desativava pura e simplesmente o controlo.

3. O quota horário por endereço

5 reservas por hora e por âmbito. Em IPv4, o âmbito é o endereço; em IPv6, é o prefixo /64 — um atacante dispõe aí de 2⁶⁴ endereços, contar o endereço inteiro não limitaria nada.

O contador só é incrementado depois da validação do formulário: um visitante que erre o email três vezes seguidas deixa de ficar bloqueado uma hora sem razão.

4. O limite diário de pedidos não verificados

No máximo 3 pedidos a aguardar validação por email podem reter um horário no mesmo dia. Sem este limite, alguns envios bastavam para congelar todos os horários de uma data. Acima disso, o visitante é convidado a tentar de novo mais tarde ou a escolher outro dia (HTTP 429).

5. O bloqueio de reserva

A reserva de um horário e o consumo de um convite fazem-se numa secção crítica serializada por um bloqueio nomeado MySQL, cujo nome deriva da sua base de dados e do seu prefixo de tabelas (dois sites do mesmo alojamento partilhado não se bloqueiam, portanto, mutuamente). Se o bloqueio não for obtido em 5 segundos, o pedido devolve um HTTP 503 explícito em vez de uma marcação duplicada.

Este bloqueio substitui, desde a 1.3.0, uma transação que assentava num SELECT simples: sob REPEATABLE READ, ele não coloca qualquer bloqueio de linha, e dois visitantes simultâneos podiam reservar o mesmo horário.

E a dupla verificação

É a camada mais eficaz: mesmo ultrapassando tudo o que precede, um robô nunca chega à sua agenda nem à sua caixa de correio, já que a notificação de administração só é enviada depois do clique num link recebido por email. Ver A dupla verificação por email.


RGPD

Uma agenda de marcações manipula dados potencialmente de saúde, contactos e históricos. As definições por defeito são deliberadamente conservadoras.

Consentimento

A caixa de consentimento é obrigatória e não está assinalada por defeito no formulário público: «Aceito que os meus contactos sejam utilizados para a gestão da minha marcação.» Uma reserva sem consentimento é recusada do lado do servidor, e não apenas do lado do navegador.

Minimização

  • Nenhum endereço IP é armazenado na base de dados. O quota horário usa um contador temporário (transient) cuja chave é um resumo do âmbito de rede, purgado ao fim de uma hora.
  • Nenhum user agent, nenhum rastreador, nenhum cookie colocado pelo plugin.
  • Nenhum dado é enviado a um serviço de terceiros: sem CDN, sem chamada externa, sem telemetria.
  • Os pedidos nunca validados são eliminados ao fim de 48 horas — não deixam nenhum dado atrás de si.
  • As marcações anuladas deixam de ser devolvidas pela API da agenda: os dados pessoais desnecessários não circulam.

Anonimização automática

Definição retention_months, 24 meses por defeito. A cada hora, as marcações terminadas há mais tempo do que esse prazo são anonimizadas no local: o nome é substituído por «Anonimizado», o telefone e o email são esvaziados, a mensagem do cliente e as notas internas são apagadas. A linha permanece, o que preserva o histórico estatístico da atividade (quantas marcações, quando, para que serviço) sem conservar o menor dado pessoal.

Coloque 0 para desativar a anonimização automática — com plena consciência.

Nota: a anonimização visa as marcações que têm um endereço de email. Uma marcação introduzida à mão sem email (apenas nome e telefone) não é atingida pela purga automática; elimine-a manualmente se a sua política de retenção o exigir.

Direito de acesso e direito ao apagamento

O plugin não liga os exportadores/apagadores nativos do WordPress (estes trabalham sobre contas de utilizador, e os clientes não as têm). Para tratar um pedido:

  • Acesso — procure a pessoa no diretório de clientes (nome, telefone ou email) e percorra as suas marcações na agenda. Os administradores de base de dados podem também interrogar diretamente {prefix}_owag_appointments e {prefix}_owag_customers na coluna customer_email / email.
  • Apagamento — elimine a ficha do diretório, depois anule ou deixe anonimizar as marcações em causa. Uma eliminação imediata faz-se na base de dados sobre customer_email.
-- Effacement manuel des données personnelles d'une personne (adaptez le préfixe).
UPDATE wp_owag_appointments
   SET customer_name = 'Anonymisé', customer_phone = '', customer_email = '',
       customer_msg = NULL, admin_notes = NULL
 WHERE customer_email = 'personne@example.com';

DELETE FROM wp_owag_customers WHERE email = 'personne@example.com';

Registo das atividades de tratamento

Para o seu registo: finalidade gestão das marcações; fundamento jurídico consentimento (reserva online) ou execução de um contrato / diligências pré-contratuais (marcação feita por telefone); categorias identidade, contactos, conteúdo da mensagem, notas internas; prazo 24 meses por defeito, seguido de anonimização; destinatários nenhum subcontratante além do seu alojamento e do seu serviço de envio de emails.


Shortcodes

[ow_agenda] — a reserva pelo visitante

A colocar numa página pública. Sem atributos: o serviço, a duração e os horários vêm das definições. O shortcode carrega a sua folha de estilos e o seu script (menos de 12 KB no total, sem dependências) e devolve um contentor que se preenche depois da primeira chamada à API.

[ow_agenda]

É este shortcode que interpreta o parâmetro de URL ?owag_invite=<token>: a mesma página serve a consulta padrão e as sessões por convite.

[ow_agenda_admin] — a página de gestão

A colocar numa página dedicada. Sem atributos. O shortcode gere ele próprio o acesso:

  • visitante sem sessão iniciada → link de início de sessão que devolve à página;
  • com sessão iniciada mas sem a capacidade owag_manage → mensagem de acesso restrito;
  • com sessão iniciada e com a capacidade → a interface completa (agenda, pendentes, clientes, convites).
[ow_agenda_admin]

As duas páginas são criadas automaticamente na ativação com estes shortcodes. Se as tiver eliminado, basta criar uma página e colar-lhe o shortcode — não se esqueça então de atualizar a opção owag_page_admin (ou owag_page_booking) para que os links dos emails e o manifesto apontem para o sítio certo.

As páginas autónomas

Quatro parâmetros de URL, intercetados em qualquer página do site, produzem páginas autónomas servidas fora do tema (renderização mínima, noindex,nofollow):

URLFunção
?owag_verify=<uid>Validação do pedido pelo cliente (duplo opt-in)
?owag_cancel=<uid>Anulação online pelo cliente
?owag_admin_action=confirm|refuse&uid=…&sig=…Confirmação / recusa a partir do email de administração
?owag_manifest=1Manifesto de aplicação da página Agenda

Estas páginas nunca executam qualquer ação ao carregar: mostram um resumo e um botão. Nenhum robô, nenhum antivírus de correio, nenhum prefetch de navegador pode confirmar ou anular uma marcação em lugar de um humano.


API REST

Todos os endpoints vivem sob o namespace owag/v1, na raiz REST habitual (https://example.com/wp-json/owag/v1/…).

Endpoints públicos

Sem autenticação: são as rotas do widget de reserva e dos links recebidos por email. A sua segurança assenta em tokens aleatórios (32 caracteres hexadecimais gerados por um gerador criptográfico), em assinaturas HMAC e nas proteções descritas em Anti-spam.

MétodoCaminhoParâmetrosFunção
GET/public/daysfrom (Y-m-d, por defeito: hoje), token (convite, facultativo)Devolve label, duration e days: 14 dias a partir de from, cada um com o seu número de horários livres
GET/public/slotsdate (Y-m-d, obrigatório), tokenDevolve slots: as horas de início livres (HH:MM)
POST/public/bookdate, time, name, phone, email, message, consent, website (armadilha), ts (carimbo temporal), tokenCria o pedido; devolve status e a mensagem a apresentar
POST/public/verifyuidValida um pedido unverified
POST/public/canceluidAnula uma marcação pending ou confirmed, dentro do limite do aviso prévio
POST/public/admin-actionuid, action (confirm|refuse), sigConfirma ou recusa a partir do email de administração (assinatura HMAC)

Exemplo de reserva:

curl -X POST https://example.com/wp-json/owag/v1/public/book \
  -H 'Content-Type: application/json' \
  -d '{
    "date": "2026-09-15",
    "time": "14:30",
    "name": "Marie Dupont",
    "phone": "0470 12 34 56",
    "email": "marie@example.com",
    "message": "Première visite",
    "consent": 1,
    "website": "",
    "ts": 1757942400
  }'
{
  "ok": true,
  "status": "unverified",
  "message": "Un dernier geste : un e-mail vient de vous être envoyé…"
}

Endpoints de administração

Todos exigem a capacidade owag_manage e um nonce REST do WordPress válido (cabeçalho X-WP-Nonce).

MétodoCaminhoParâmetrosFunção
GET/admin/agendafrom, to (Y-m-d)events (o intervalo pedido, anulados excluídos) e pending (todos os pedidos pendentes futuros)
POST/admin/appointmentkind (manual|block|consult|seance), date, time, duration (5–720 min), label, name, phone, email, notes, force, send_emailCria uma marcação manual ou um bloqueio
POST/admin/appointment/{id}status (pending|confirmed|cancelled|done|noshow), name, phone, email, label, notes, date, time, duration, force, silentAtualiza, remarca, muda o estado. silent=1 suprime qualquer envio de email
GET/admin/customersq (pesquisa)O diretório (200 fichas no máximo)
POST/admin/customersname (obrigatório), phone, email, notesCria uma ficha
POST/admin/customers/{id}idemAtualiza uma ficha
DELETE/admin/customers/{id}Elimina uma ficha
GET/admin/invitesOs convites abertos (nunca usados ou libertados, não expirados)
POST/admin/invitesname (obrigatório), label (obrigatório), duration (15–720), days_valid (1–365, por defeito 60), email, phone, send_emailCria um convite; devolve url e email_sent
DELETE/admin/invites/{id}Elimina um convite
GET/admin/settingsAs definições efetivas
POST/admin/settingscorpo JSON (ver Referência das definições)Guarda as definições

Cada rota declara explicitamente o seu controlo de acesso; a capacidade é verificada antes da execução do menor tratamento.

Códigos de erro

Os erros são WP_Error padrão, com um código legível e um estado HTTP.

CódigoHTTPSignificado
owag_spam403Armadilha para robôs preenchida, ou carimbo temporal em falta / demasiado recente
owag_rate429Quota horário atingido para este endereço
owag_day_full429Demasiados pedidos a aguardar validação nesta data
owag_busy503Bloqueio de reserva não obtido — tentar novamente dentro de instantes
owag_slot_taken409Horário ocupado entretanto
owag_overlap409Sobreposição detetada (admin) — reenviar com force
owag_invite_invalid404Token de convite desconhecido
owag_invite_used410Convite já consumido
owag_invite_expired410Convite expirado
owag_too_late403Anulação online fora do prazo de aviso prévio
owag_bad_sig403Assinatura HMAC inválida
owag_not_found404Marcação ou ficha não encontrada
owag_name, owag_phone, owag_email, owag_consent400Campo inválido ou consentimento em falta
owag_bad_input, owag_bad_date400Data, hora ou introdução inválida
owag_noop400Pedido de atualização vazio
owag_insert500Falha de escrita na base de dados

Hooks para programadores

Na 1.3.1, o OW Agenda não expõe nem filtro nem action pública: não há API de extensão a documentar, e nada do que se segue deve ser adivinhado. O único hook utilizável é o evento agendado owag_hourly_event, ao qual pode ligar a sua própria manutenção:

add_action( 'owag_hourly_event', function () {
    // Votre traitement horaire, exécuté juste après celui du plugin.
} );

Para todo o resto, a API REST é o ponto de integração: expõe exatamente aquilo que a interface faz, nem mais nem menos.


Referência das definições

Todas as definições cabem numa única opção, owag_settings. Leitura e escrita em PHP:

$s = owag_settings();          // réglages effectifs (défauts + enregistrés)
$duree = (int) $s['consult_duration'];

update_option( 'owag_settings', array_merge( owag_settings(), [
    'consult_duration' => 45,
    'buffer'           => 10,
] ) );

Valores por defeito

[
    // Horaires : clé = 1 (lundi) … 7 (dimanche), valeur = liste de plages [début, fin]
    'hours' => [
        '1' => [ [ '09:00', '18:00' ] ],
        '2' => [ [ '09:00', '18:00' ] ],
        '3' => [ [ '09:00', '18:00' ] ],
        '4' => [ [ '09:00', '18:00' ] ],
        '5' => [ [ '09:00', '18:00' ] ],
        '6' => [],   // samedi fermé
        '7' => [],   // dimanche fermé
    ],
    'slot_step'           => 30,   // granularité des créneaux proposés (minutes)
    'consult_duration'    => 60,   // durée d'une consultation (minutes)
    'buffer'              => 0,    // battement autour de chaque rendez-vous (minutes)
    'min_notice_hours'    => 24,   // délai minimum avant réservation
    'max_advance_days'    => 60,   // horizon maximum de réservation
    'auto_confirm'        => 0,    // 0 = validation manuelle, 1 = confirmation automatique
    'email_verify'        => 1,    // double vérification par e-mail
    'cancel_notice_hours' => 24,   // préavis d'annulation en ligne par le client
    'notify_email'        => get_option( 'admin_email' ),
    'retention_months'    => 24,   // anonymisation des RDV passés (0 = jamais)
    'consult_label'       => 'Consultation',
]

Detalhe

DefiniçãoTipoLimites da interfaceEfeito
hoursarray1 ou 2 períodos por diaDois períodos permitem a pausa de almoço. Um período só é considerado se o início e o fim forem válidos e se início < fim. Um dia vazio = fechado
slot_stepinteiro5 → 120 minEspaçamento das horas propostas. Quanto mais fino, mais longa é a lista
consult_durationinteiro15 → 480 minDuração reservada na agenda para uma consulta web
bufferinteiro0 → 120 minIntervalo aplicado de um lado e do outro do horário candidato
min_notice_hoursinteiro0 → 168 hNada é proposto antes de agora + este prazo
max_advance_daysinteiro7 → 365 dHorizonte para além do qual nenhum horário é proposto
auto_confirm0 / 1Validação manual ou confirmação imediata
email_verify0 / 1Duplo opt-in por email (a deixar ativo)
cancel_notice_hoursinteiro0 → 168 hPara além disso, a anulação online é recusada com uma mensagem que convida a telefonar
notify_emailemailDestinatário das notificações de administração; serve também de ORGANIZER nos ficheiros ICS
retention_monthsinteiro0 → 120 mesesAnonimização das marcações terminadas; 0 desativa
consult_labeltextoTítulo apresentado no widget de reserva

Duas constantes não configuráveis merecem ser conhecidas, porque governam o comportamento do duplo opt-in: o horário de um pedido não verificado fica retido 45 minutos, e o pedido é eliminado ao fim de 48 horas.

O registo pela API REST aceita as mesmas chaves em JSON; os inteiros são reduzidos a zero no mínimo, o endereço de notificação só é aceite se for válido, e cada período horário é revalidado do lado do servidor.


Dados armazenados

Três tabelas, todas com o prefixo da sua instalação. As datas são DATETIME em hora local do site, nunca em UTC — é isso que torna as consultas legíveis e as comparações de horários triviais.

{prefix}_owag_appointments

ColunaTipoNotas
idBIGINTChave primária
uidCHAR(32)Token público único (hexadecimal, gerador criptográfico). Serve de chave aos links de validação, de anulação e de ação de administração, e de UID ICS
kindVARCHAR(16)consult, seance, manual, block
service_labelVARCHAR(120)Designação apresentada
customer_name, customer_phone, customer_emailVARCHARContactos
customer_msgTEXTMensagem deixada pelo cliente
admin_notesTEXTNotas internas, nunca enviadas ao cliente
start_dt, end_dtDATETIMELimites do horário (indexados em start_dt)
statusVARCHAR(16)unverified, pending, confirmed, cancelled, done, noshow
sourceVARCHAR(16)web, invite, admin
invite_idBIGINTConvite de origem, se aplicável
reminder_sentTINYINTFlag de lembrete (reposta a 0 em caso de remarcação)
created_at, updated_atDATETIMEupdated_at alimenta o número de revisão ICS

{prefix}_owag_invites

id, token (CHAR(32), único), contactos do cliente, service_label, duration_min, expires_at, appointment_id (preenchido quando o link é consumido, reposto a NULL se a marcação for anulada), created_at.

{prefix}_owag_customers

id, name, phone, email, notes, created_at, updated_at. Índice em name e email.

Uma única opção transporta a configuração (owag_settings); as outras são técnicas: owag_admin_secret (segredo HMAC), owag_db_version, owag_pages_created, owag_page_booking, owag_page_admin.


Internacionalização

Toda a interface é traduzível: definições de administração, widget de reserva, página Agenda, páginas autónomas, mensagens da API e modelos de email. A língua de origem é o inglês; o plugin declara o domínio de tradução ow-agenda e o caminho /languages.

O pacote entrega o modelo languages/ow-agenda.pot. É fornecida uma tradução francesa completa, produzida a partir da formulação de origem da interface.

Instalar uma tradução manualmente

Compile o .po e coloque o .mo na pasta de traduções do WordPress:

msgfmt ow-agenda-fr_FR.po -o ow-agenda-fr_FR.mo
# puis : wp-content/languages/plugins/ow-agenda-fr_FR.mo

O WordPress carrega o catálogo na primeira cadeia traduzida; nenhuma chamada manual é necessária.

Duas armadilhas para os tradutores

  • As cadeias destinadas ao JavaScript usam marcadores numerados (%1$s, %2$s) e nunca um %s simples: o pequeno formatador embutido nos scripts só compreende esses. Um marcador não numerado seria apresentado literalmente.
  • Duas cadeias são formatos de data PHP, não frases: l, F j, Y \a\t g:i a e l j F Y \a\t H:i. Traduza-as como formatos (reordenar os tokens, escapar as letras literais com uma barra invertida). O francês usa l j F Y \à H\hi.

Desinstalação

Desativar o plugin faz apenas uma coisa: eliminar a tarefa agendada horária. Os seus dados, as suas definições e as suas páginas ficam intactos, e tudo recomeça na reativação.

Eliminar o plugin a partir do WordPress executa a desinstalação completa:

  • eliminação das três tabelas (owag_appointments, owag_invites, owag_customers);
  • eliminação das opções owag_settings, owag_admin_secret, owag_db_version, owag_pages_created, owag_page_booking, owag_page_admin;
  • eliminação da tarefa agendada;
  • remoção da capacidade owag_manage do papel administrador.

As duas páginas criadas na ativação não são eliminadas — podem ter sido retrabalhadas, colocadas num menu, indexadas. Cabe-lhe a si enviá-las para a reciclagem se já não as quiser.

A eliminação das tabelas é definitiva. Exporte a sua base de dados antes se o histórico das marcações tiver valor para si.


Resolução de problemas

Não aparece nenhum horário na página de reserva

Percorra a lista por ordem:

  1. O horário do dia está preenchido? Um dia vazio é um dia fechado.
  2. A antecedência mínima (24 h por defeito) esconde forçosamente hoje e uma parte de amanhã.
  3. A duração cabe no período? Com um período 09:00–12:00 e uma duração de 240 minutos, nenhum horário pode existir.
  4. O horizonte: os dias para além de max_advance_days nunca são propostos.
  5. O intervalo: um intervalo largo num planeamento carregado pode fechar tudo.
  6. Um bloqueio cobre talvez o dia. Abra a página Agenda no dia em causa.
  7. O fuso horário do site (Definições → Geral): um fuso mal configurado desloca todos os cálculos.

Os emails não chegam

É quase sempre a entregabilidade, não o plugin.

  1. Verifique se a marcação existe mesmo na página Agenda: se lá estiver, o plugin fez o seu trabalho.
  2. Instale um plugin SMTP (Fluent SMTP, WP Mail SMTP…). A função mail() do PHP é rejeitada pela esmagadora maioria dos servidores de receção.
  3. Verifique o SPF, o DKIM e o DMARC do seu domínio.
  4. Teste o endereço em OW Agenda → Notificações de administração enviadas para: um endereço inválido bloqueia silenciosamente as notificações.

O lembrete da véspera não saiu

O lembrete depende do WP-Cron, que depende do tráfego. Num site pouco visitado, passe para um verdadeiro cron de sistema (ver Lembretes e tarefa agendada). Verifique também que a marcação está mesmo confirmada, que tem um endereço de email e que não é um bloqueio.

A página Agenda mostra «O acesso é reservado à equipa»

O utilizador com sessão iniciada não tem a capacidade owag_manage. Ela é dada aos administradores na ativação; para os outros papéis, ver Instalação.

O botão «Confirmar» do email mostra «Link inválido»

Três causas possíveis: o link foi truncado pelo cliente de correio (tente copiar o URL completo), a marcação já foi tratada (a mensagem indica-o), ou o segredo HMAC do site foi regenerado. Neste último caso, passe pela página Agenda: os links antigos já não podem ser validados, por construção.

Duas marcações ficam no mesmo horário

Desde a 1.3.0, isso é impossível através da reserva online. Em contrapartida, o administrador pode forçar uma sobreposição a partir da página Agenda (o plugin assinala-o e pede confirmação): verifique primeiro se não se trata de uma forçagem voluntária. Verifique também se a sua base de dados suporta bem GET_LOCK() — um alojamento exótico devolveria então erros 503 na reserva em vez de duplicados.

As páginas «Marcar» e «Agenda» não foram criadas

Só são criadas uma vez, na primeiríssima ativação. Se as tiver eliminado, crie duas páginas com os shortcodes [ow_agenda] e [ow_agenda_admin], e depois aponte-lhes as opções owag_page_booking e owag_page_admin para que os links dos emails continuem corretos:

update_option( 'owag_page_booking', 42 );  // ID de votre page de réservation
update_option( 'owag_page_admin', 43 );    // ID de votre page Agenda

O ficheiro de calendário não vem anexado

O ficheiro é escrito no diretório temporário do servidor através da API de ficheiros do WordPress. Se esse diretório não estiver acessível para escrita (quota, permissões, alojamento trancado), o email parte sem anexo em vez de falhar. Verifique as permissões de escrita e o espaço em disco.

Os horários estão desfasados uma hora

Definições → Geral → Fuso horário. Escolha uma cidade (Europe/Lisbon) em vez de um desvio UTC fixo: só um fuso nomeado gere a passagem à hora de verão.


FAQ

O OW Agenda é mesmo gratuito? Sim. GPL-2.0-or-later, descarregável em .zip de https://optionweb.dev/pt/addons/ow-agenda/. Sem versão Pro, sem chave de licença, sem funcionalidade bloqueada, sem conta a criar, sem quota de marcações.

Os horários online têm em conta as marcações feitas por telefone? Sim. Qualquer evento da agenda — reserva web, marcação introduzida à mão, sessão por convite, bloqueio — torna o seu período horário indisponível para a reserva online.

O cliente tem de criar uma conta? Não. Nenhuma conta, nenhuma palavra-passe. Todas as ações do cliente (validação, anulação) passam por links privados recebidos por email.

É possível gerir vários profissionais ou várias salas? Não. O OW Agenda descreve um único planeamento. Para duas agendas independentes, são precisos dois sites (ou dois sites de uma rede multisite).

Sincroniza com o Google Calendar? No sentido que conta para o cliente: sim. Cada confirmação transporta um ficheiro de calendário padrão que adiciona — e atualiza, e elimina — o evento no Google Calendar, no Outlook ou no calendário do iPhone. Em contrapartida, o plugin não lê as suas agendas externas: as suas indisponibilidades pessoais introduzem-se como bloqueios.

É possível cobrar um sinal na reserva? Não, está fora do perímetro assumido do plugin.

Quantos serviços se podem propor online? Apenas um, cuja designação e duração escolhe. Os restantes serviços passam pelos convites de sessão, que lhe permitem definir a designação e a duração caso a caso. Esta escolha é deliberada: um menu de serviços numa página pública multiplica os pedidos mal direcionados.

Funciona num multisite? Sim. Cada site da rede tem as suas próprias tabelas, as suas próprias definições e a sua própria agenda.

O plugin torna o site mais lento? Não. Nenhum script é carregado fora das duas páginas em causa; o widget de reserva pesa menos de 12 KB, sem jQuery nem framework. O trabalho periódico cabe numa tarefa horária.

O que acontece se um cliente nunca validar o seu email? O seu horário volta a ficar disponível ao fim de 45 minutos e o seu pedido é eliminado ao fim de 48 horas. Nunca ouve falar do assunto.

Onde encontrar o suporte?


Changelog

1.3.1

Conformidade

  • As páginas autónomas de ação, de verificação e de anulação deixaram de imprimir o seu CSS e o seu JavaScript inline: ambos são agora ficheiros registados e servidos pela API de enqueue do WordPress. As duas cores variáveis dos botões passam por propriedades CSS personalizadas, e o script é configurado através de wp_localize_script().
  • Os catálogos de tradução deixaram de ser incorporados: só languages/ow-agenda.pot é entregue, sendo o francês distribuído pelos pacotes de idioma do WordPress.org alimentados por translate.wordpress.org.
  • A versão mínima do WordPress volta a 6.3: nada no pacote depende já da deteção das traduções incorporadas introduzida na 6.7.

API REST

  • Cada rota de administração declara agora o seu permission_callback explicitamente em vez de o partilhar através de array_merge(). O controlo de capacidade já era aplicado; agora está visível para a análise estática.

Nenhuma alteração de comportamento.

1.3.0

Internacionalização

  • Plugin totalmente traduzível (domínio ow-agenda, inglês como língua de origem): definições, páginas públicas, mensagens da API, emails e interface JavaScript.
  • Modelo languages/ow-agenda.pot entregue e tradução francesa completa.

Segurança

  • Os identificadores públicos das marcações e os tokens de convite são gerados por um gerador criptográfico (random_bytes()). Estes tokens são a única autenticação dos links de anulação, de validação e de convite.
  • A armadilha para robôs e o carimbo temporal tornaram-se obrigatórios: omiti-los desativava os controlos anti-spam.
  • O quota horário é agregado por prefixo /64 em IPv6, e um limite diário restringe os pedidos não verificados — um visitante deixa de poder reter todos os horários de um dia.
  • O quota só é descontado depois da validação do formulário: um erro de escrita deixa de bloquear um visitante legítimo durante uma hora.

Fiabilidade

  • As reservas simultâneas de um mesmo horário são serializadas por um bloqueio nomeado MySQL. A transação anterior não colocava qualquer bloqueio de linha: dois visitantes podiam reservar o mesmo horário.
  • O lembrete da véspera usa uma janela deslizante de 12 a 36 h e recupera o seu atraso; cada envio é reservado de forma atómica, duas execuções de cron deixaram de poder enviar duas vezes o mesmo lembrete.
  • A tarefa horária reagenda-se automaticamente se desaparecer: lembretes, purga e anonimização deixaram de poder parar em silêncio.
  • A remarcação de uma consulta atualiza o calendário do cliente (SEQUENCE, METHOD:REQUEST, organizador e participante); a anulação envia um METHOD:CANCEL que elimina o evento.
  • As datas do widget são calculadas em hora local e não em UTC: acabaram os dias perdidos para os visitantes a leste de UTC.
  • A anulação de uma marcação resultante de um convite liberta o convite, que volta a ficar utilizável.
  • As marcações anuladas e os pedidos não validados expirados deixaram de ser devolvidos à agenda: menos dados pessoais nas respostas, sem marcações fantasma.

1.2.1

  • Conformidade Plugin Check: escape das saídas, sanitização das entradas, nonce nas definições, readme.
  • A desinstalação elimina também a tabela do diretório de clientes e o segredo HMAC.

1.2.0

  • Emails HTML (composição em cartão, cor de destaque do site) para todas as notificações.
  • Botões Confirmar / Recusar no email de administração (links assinados HMAC).
  • Diretório de clientes: pesquisa, criação, edição, eliminação, atalhos para uma nova marcação e um convite.

1.1.0

  • Dupla verificação por email contra os robôs (horário retido 45 minutos, purga ao fim de 48 horas).

1.0.0

  • Versão inicial: reserva online, agenda de administração mobile-first, convites de sessão, emails com ficheiro de calendário e lembrete da véspera.

Concebido por OptionWeb — Julien Daniel, Châtelet, Bélgica.