feat: aulas experimentais guardadas, anti-spam partilhado nos formulários, audit das escritas
- Pedido de aula experimental passa a ficar em trial_leads (por ginásio) ANTES do email: sem SMTP o visitante já não vê «erro» e o pedido não se perde. Gestão → Aulas experimentais: estados, notas, CSV (auditado), apagar para a lixeira; aviso «sem email» quando o aviso não saiu. - Aula experimental, inscrição e eventos usam o anti-spam do platform-tools (honeypot, carimbo assinado com tempo mínimo, prova de JS, limite por IP, pontuação de conteúdo) e o bloqueio de IP, em vez de honeypots locais. Recusas ficam em blocked_submissions; resposta igual à de sucesso. Falha aberto se o módulo rebentar. - Checkbox de consentimento da aula experimental passa a ser guardada. - Audit das escritas de conteúdo: criar/editar equipa, modalidades, eventos, mensalidades, pedidos de inscrição, galerias, horário (incl. arrastar no calendário), horas, contactos e ginásios, com antes/depois campo a campo (audit_row/audit_change). Exportação CSV de inscrições auditada. - .table-responsive em todas as tabelas do backoffice. - Migração: database/migration_20260926_trial_leads.sql (só cria tabelas). Testado numa cópia da BD de produção: 63/63 verificações HTTP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0e8b53f620
commit
04c8c83e66
29 files changed
+480
-29
No files matched your search
@@ -0,0 +1,51 @@
|
||||
-- ─── Pedidos de aula experimental + registo do anti-spam ────────────────────
|
||||
-- Até aqui o pedido de aula experimental só existia como email: sem SMTP (ou
|
||||
-- com o SMTP em baixo) o visitante via «erro» e o pedido perdia-se. Agora fica
|
||||
-- guardado primeiro, como as inscrições, e o email é só um aviso.
|
||||
--
|
||||
-- blocked_submissions: onde o anti-spam partilhado (platform-tools,
|
||||
-- functions_antispam_forms.php) guarda o que recusou — um falso positivo é uma
|
||||
-- lead verdadeira, e tem de se poder ler. Esquema igual ao do dance.
|
||||
--
|
||||
-- Só cria tabelas. Safe to re-run.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `trial_leads` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`gym_id` INT NOT NULL DEFAULT 1,
|
||||
`name` VARCHAR(150) NOT NULL,
|
||||
`email` VARCHAR(190) NOT NULL DEFAULT '',
|
||||
`phone` VARCHAR(40) NOT NULL DEFAULT '',
|
||||
`preferred_date` DATE NULL DEFAULT NULL,
|
||||
`period` VARCHAR(40) NOT NULL DEFAULT '',
|
||||
`message` TEXT NULL,
|
||||
`consent` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`consent_text` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`ip` VARCHAR(45) NOT NULL DEFAULT '',
|
||||
`user_agent` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`status` VARCHAR(20) NOT NULL DEFAULT 'novo',
|
||||
`admin_notes` TEXT NULL,
|
||||
`email_sent` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`updated_by` INT UNSIGNED NULL DEFAULT NULL,
|
||||
`deleted_at` DATETIME NULL DEFAULT NULL,
|
||||
`deleted_by` INT UNSIGNED NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_trial_leads_gym` (`gym_id`, `deleted_at`, `status`),
|
||||
KEY `idx_trial_leads_ip` (`ip`, `created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blocked_submissions` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`form` VARCHAR(40) NOT NULL COMMENT 'trial, inscricao, evento',
|
||||
`reason` VARCHAR(190) NOT NULL COMMENT 'Regra que travou, ou os sinais somados',
|
||||
`score` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Pontuação de conteúdo; 0 nas recusas diretas',
|
||||
`ip` VARCHAR(45) NOT NULL DEFAULT '',
|
||||
`user_agent` VARCHAR(250) NOT NULL DEFAULT '',
|
||||
`payload` TEXT DEFAULT NULL COMMENT 'JSON do que foi submetido, sem o token CSRF',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_bs_form` (`form`),
|
||||
KEY `idx_bs_ip` (`ip`),
|
||||
KEY `idx_bs_created` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
Reference in new issue
Block a user