Cerebro Studio · Backlog · Changelog
RioNoTeatro • /www/wwwroot/rionoteatro.com.br/docs/changelog/2026/CL-2026-09-10-BK-410-convite-parceria-produtor.md • 2026-09-10T21:25:17.581Z

CL-2026-09-10 — BK-410: convite automatico de parceria 3 dias apos a aprovacao da peca

Pedido do dono (10/09/2026)

> "Apos um produtor incluir no site e eu aprovar a peca, caso ele nao tenha solicitado a

> parceria gratuita com venda, depois de 3 dias da aprovacao da peca dele devemos enviar

> uma mensagem automatica para o produtor" — com saudacao conforme a hora, nome do

> produtor, a oferta de 20% de comissao e o link do TERMO DE PARCERIA RIONOTEATRO.

Decisoes tomadas com o dono na mesma rodada:

  • link do termo: pagina publica nova, nao o painel;
  • repeticao: 1 convite por peca (produtor com varias pecas sem parceria recebe um por peca);
  • janela de envio: 09h as 20h (horario de Brasilia).

O que existia antes

  • pecas.parceria_online = 1 ja era a marca de "produtor pediu a parceria com venda online"

(checkbox do painel do produtor, que dispara ajax_notificar_parceria.php para o admin).

  • A aprovacao da peca ja mandava WhatsApp ao produtor (acao_admin=aprovar).
  • Nao existia data de aprovacao em lugar nenhum — sem isso nao havia como contar 3 dias.
  • O Termo de Parceria so existia dentro do modal do painel (exige login) e num PDF em

SQL/BKP/, que o nginx nao serve (403) — nenhum dos dois servia como link de WhatsApp.

O que foi entregue

Banco

  • pecas.aprovada_em DATETIME NULL — carimbo da PRIMEIRA aprovacao.
  • rnt_convite_parceria_log (peca_id UNIQUE) — dedup de 1 convite por peca, para sempre.

admin/modulos/eventos/action.php

  • Nova funcao marcarPrimeiraAprovacaoEvento(), chamada nos DOIS caminhos em que o admin

aprova: o botao Aprovar (acao_admin=aprovar) e a edicao salva com status = 'A'.

  • Grava com NOW() do MySQL de proposito: o date.timezone desta VPS e PRC, entao

date() no PHP daria a hora errada.

  • So grava quando aprovada_em IS NULL: se o produtor editar, a peca voltar para I e o

admin aprovar de novo, vale a data da primeira aprovacao.

termo-parceria.php (novo, publico, HTTP 200)

  • Mesmo texto do modal do painel, sem login, para poder ser linkado por WhatsApp.
  • O texto agora esta duplicado em tres lugares (esta pagina + os dois modais do painel):

ao mudar o termo, mudar os tres.

admin/cron/convite_parceria_produtor.php (novo) + /etc/cron.d/rnt-convite-parceria-produtor

  • Roda a cada 30 min entre 9h e 20h; o proprio script reconfere a janela com

DateTimeZone('America/Sao_Paulo') explicito, porque a saudacao depende da hora.

  • Elegibilidade: origem='produtor', status='A' agora, parceria_online=0,

aprovada_em <= NOW() - 3 dias, temporada viva (fim_temporada >= CURDATE()),

produtor com celular e sair=0, e id_produtor <> BOT_PRODUTOR_ID.

  • Guardrails: --dry-run, --preview, --test-send (numero fixo do gestor 21999915554),

no maximo 10 convites por rodada e no maximo 1 por produtor por rodada.

  • Log em /www/server/cron/rnt_convite_parceria_produtor.log (fora do webroot).

Ressalva de texto

A mensagem cita o nome do evento ("Seu evento X ja esta publicado...") alem do texto

ditado pelo dono. Isso nao e enfeite: como o dedup e por peca, dois eventos do mesmo

produtor gerariam duas mensagens de texto identico, e o anti-spam de 24h do

whatsapp_helper bloquearia a segunda e ainda alertaria o gestor como se fosse loop.

Segunda leitura (gpt-6-astra) e as 6 correcoes que ela gerou

A revisao independente achou defeitos reais, todos conferidos na fonte antes de agir:

  1. Anti-spam matava a 2a peca do mesmo produtor, para sempre. _whatsapp_pode_enviar_pro_cliente

usa md5(numero + ULTIMOS 100 BYTES da mensagem) (includes/whatsapp_helper.php:1414) e o

fim do convite (link do termo) e igual em toda peca. Duas pecas do mesmo produtor em 24h:

a segunda era bloqueada, gravada como tentativa e nunca mais reenviada.

Correcao: produtor com tentativa nas ultimas 25h nao entra na selecao, e a peca so sai

do funil quando enviado=1 ou apos CONVITE_MAX_TENTATIVAS.

  1. Havia 4 caminhos que publicam a peca sem carimbar aprovada_em — conciliar_aplicar_update

e conciliar_reativar (eventos), case editar e toggle_status (admin/modulos/pecas/action.php).

Correcao: a funcao virou helper compartilhado includes/rnt_aprovacao_peca_helper.php,

chamado nos 7 caminhos de ativacao.

  1. Editar peca ja ativa carimbava aprovacao nova — o teste era so $_POST['status']==='A',

sem exigir transicao. Uma peca antiga viraria candidata a convite 3 dias depois de uma

edicao qualquer. Correcao: o helper recebe o status ANTERIOR e so carimba em != 'A' -> 'A'.

  1. UNIQUE(peca_id) nao impedia envio duplo — o WhatsApp saia antes do INSERT.

Correcao: a linha do log e reservada ANTES do envio e so vira enviado=1 depois da confirmacao.

  1. Erro de SQL se passava por "nenhum candidato" (mesma saida, exit 0), o que deixaria a

automacao parada em silencio. Correcao: erro de consulta loga e sai com codigo 1.

  1. fwrite(STDERR, ...) no guard de nao-CLI seria fatal em PHP-FPM (a constante nao existe

fora do CLI) e acordaria o vigia de erros. Correcao: responde 404 e sai.

Trigger no banco resolveria os itens 2 e 3 de uma vez, mas o usuario do MySQL **nao tem

privilegio para criar trigger** (SUPER com binlog ligado) — por isso a cobertura e por helper.

O astra tambem levantou que a fila do WhatsApp (quando o servico esta offline) reenvia sem

revalidar opt-out/elegibilidade: e verdade, vale para todas as automacoes do RNT e nao foi

tratado aqui.

Validacao feita

  • php83 -l nos tres arquivos.
  • --preview com peca real (1613 SILVAS): saudacao correta para a hora de Brasilia.
  • Simulacao com aprovada_em = NOW() - 4 DAY na peca 1613: entrou no --dry-run com a

mensagem completa; valor revertido para NULL depois do teste.

  • --test-send: WhatsApp entregue ao gestor, HTTP 200.
  • Ponta a ponta com peca de teste (id 1618, nome Teste — nome que as vitrines do site ja

excluem — apontando para o cliente 775, celular do gestor): a rodada real selecionou a peca,

reservou no log e tentou o envio. O anti-spam bloqueou **porque o --test-send de 15 min

antes tinha o mesmo final de mensagem** — ou seja, o defeito 1 foi reproduzido ao vivo, e a

peca ficou com enviado=0, tentativas=1 para retentar, exatamente como a correcao previa.

Peca de teste e linha de log apagadas depois.

  • termo-parceria.php no ar, texto integro do primeiro item ao "Proposta valida ate 20/12/2026".

Termo atualizado no mesmo dia (pedido do dono)

O dono perguntou se o termo ja dizia que a lista de compradores vai diariamente para os

telefones cadastrados, e nao mais so por e-mail. Nao dizia. O item 1.1 da Dinamica de

Venda falava so em e-mail, enquanto na pratica o z_dispara_diario.php roda todo dia as

08:01 e manda o link da lista por WhatsApp para pecas.telefone_lista — e o envio por

e-mail esta DESLIGADO por padrao (RNT_LISTA_DIARIA_EMAIL_ENABLED nao setada => "0").

Novo texto do 1.1, aplicado nos tres lugares onde o termo esta duplicado

(termo-parceria.php, painel/modulos/eventos/incluir.php, painel/modulos/eventos/editar.php):

> 1.1 – Todo dia de espetáculo, o link digital com a lista de compradores é enviado por

> WhatsApp para os telefones cadastrados no site e também para os e-mails cadastrados...

Itens 6 e 8 ficaram como estavam, por decisao do dono.

Ampliacao de alcance e backfill (mesmo dia, pedido do dono)

> "podemos enviar essa mensagem tbm p outro produtores que incluirem pecas em nosso site"

O filtro original (origem = 'produtor') so pegava a peca que o produtor cadastrou pelo

PAINEL. Ficava de fora o fluxo mais comum do runbook: **o ADMIN cadastra a partir da mensagem

do produtor**, e nesse caso a peca nasce com origem = 'admin' (7 pecas / 7 produtores reais:

Carpes Producoes, LV Comunicacoes, Antonio Fragoso...).

Agora a regra e por PRODUTOR VINCULADO, nao por origem: entra qualquer peca com

id_produtor real (diferente de 0 e do produtor-robo BOT_PRODUTOR_ID), venha do painel, do

cadastro pelo admin ou de evento do bot vinculado a produtor. Continuam fora a peca sem

produtor (venda propria do RNT), a do produtor-robo e a chamada Teste — mesma exclusao

BINARY nome <> 'Teste' que as vitrines do site ja fazem, senao a conta de teste receberia.

Backfill: peca com produtor, sem parceria e com temporada viva recebeu carimbo retroativo

de NOW() - 3 dias — a data real da aprovacao nao existe em lugar nenhum e pecas nao tem

coluna de criacao, entao esse e o melhor valor disponivel. Foram 2 pecas (as unicas com

temporada em aberto): 1583 "Filho da Mae" (fim 12/09) e 1613 "SILVAS" (fim 21/09). As 7 pecas

de origem admin ficaram de fora porque a temporada delas ja terminou.

SILVAS (1613) foi barrada a pedido do dono, que ja tinha convidado essa producao

pessoalmente. Em vez de limpar aprovada_em (que voltaria a valer numa reaprovacao), a peca

foi gravada em rnt_convite_parceria_log com enviado = 1 e tentativas = 0: o dedup fica

definitivo e o registro diz a verdade — o convite para essa peca ja foi feito, so que fora do

sistema. Sobrou 1583 "Filho da Mae" na fila.

Fecho da mensagem (pedido do dono, 10/09/2026, depois do 1o envio real)

Acrescentado abaixo do link do termo, separado por linha em branco:

> Ou seja, se não tiver vendas em nosso site, fazemos a divulgação gratuitamente.

>

> À disposição, Jorge / Equipe Rio no Teatro

Efeito colateral a lembrar: isso empurra o nome do evento ainda mais para longe dos **100

bytes finais** que o anti-spam do whatsapp_helper compara — o novo sufixo fixo e a

assinatura. Quem segura a colisao continua sendo o espacamento de 25h por produtor, nao o

texto. Trocar o fecho tambem invalida os locks antigos, entao o primeiro envio depois da

mudanca passa mesmo para numero que ja tinha recebido a versao anterior nas ultimas 24h.

Prazo e janela revistos (pedido do dono, mesmo dia)

> "pode ser de 24h a 48h dps e dentro do horario comercial. 3 dias acho mta coisa"

  • Prazo: 3 dias -> 24h (CONVITE_HORAS_APOS_APROVACAO = 24).
  • Janela: 9h-20h -> 9h-18h (CONVITE_HORA_FIM = 17, ultimo disparo 17:30), **todos os

dias da semana** — decisao do dono: produtor de teatro trabalha fim de semana, e segurar

ate segunda estouraria a propria janela de 24-48h.

  • /etc/cron.d/rnt-convite-parceria-produtor passou de /30 9-20 para /30 9-17.

Combinados, os dois dao na pratica o intervalo de 24h a 48h que o dono pediu: quem completa

24h de madrugada espera a abertura das 9h; quem completa depois das 18h espera o dia seguinte.

Ponta aberta

  • O termo agora promete os dois canais, mas o e-mail da lista diaria esta desligado

(RNT_LISTA_DIARIA_EMAIL_ENABLED nao setada). Decisao do dono foi manter o texto com os

dois; se o e-mail continuar desligado, o texto so vira verdade quando a variavel for ligada.

  • Falta o teste de ponta a ponta com aprovacao real pelo painel do admin (conferir se

aprovada_em fica preenchida). Comando pronto: ! /root/p.sh