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 = 1ja 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_idUNIQUE) — 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: odate.timezonedesta VPS ePRC, entao
date() no PHP daria a hora errada.
- So grava quando
aprovada_em IS NULL: se o produtor editar, a peca voltar paraIe 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:
- 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.
- 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.
- 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'.
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.
- 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.
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 -lnos tres arquivos.--previewcom peca real (1613 SILVAS): saudacao correta para a hora de Brasilia.- Simulacao com
aprovada_em = NOW() - 4 DAYna peca 1613: entrou no--dry-runcom 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.phpno 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-produtorpassou de/30 9-20para/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