Files
ddad130388 feat(conversoes): a venda pelo canal da conversa sai so com a chave ligada
Decisao do dono (doc 76, opcao b): "Enviar vendas pelo canal da conversa",
desligada por padrao, em Configuracoes > Conversoes.

- A chave mora em organizations.settings.conversions.report_via_channel
  (ausente = desligada). Nao numa coluna de ad_platform_connections como o
  telefone do Google: o caminho do canal existe exatamente quando nao ha
  linha de conexao direta com a Meta, e gravar a chave ali criaria a linha
  e desligaria o proprio caminho (credencial_incompleta). Sem migration.
- O handler le a chave ANTES de ler as conversas ou chamar o provedor;
  desligada, nada sai e a venda fica na pendencia sem_conexao de sempre.
  Falha ao ler a chave espera e tenta de novo.
- Action definirVendaPeloCanal (admin, suporte somente leitura, MFA,
  auditoria conversions.report_via_channel_updated) e o switch na tela,
  com t() e espanhol no dicionario.
- Fragmento e runbook dizem que vem desligado.

Contribuicao de @jmpo (#1819).

Co-authored-by: jmpo <pompa.07@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 11:14:04 -03:00

38 lines
1.7 KiB
TypeScript

/**
* "Enviar vendas pelo canal da conversa" — a chave da venda pelo canal
* intermediado (decisão do dono no doc 76, PR #1819).
*
* Mora em `organizations.settings.conversions.report_via_channel`, e não numa
* coluna de `ad_platform_connections` como o telefone do Google: o caminho do
* canal existe EXATAMENTE quando a organização não tem linha de conexão direta
* com a Meta (`sem_conexao`). Guardar a chave nessa linha criaria a linha, e a
* leitura da credencial passaria a responder `credencial_incompleta` — a chave
* ligada desligaria o próprio caminho.
*
* ⚠️ AUSENTE É DESLIGADO, e isso é a decisão: o valor da venda e o telefone do
* cliente só saem para o provedor quando a empresa pede. Toda organização que
* existe hoje chega aqui sem a chave.
*/
import type { SupabaseClient } from "@supabase/supabase-js";
export function vendaPeloCanalLigada(settings: unknown): boolean {
if (!settings || typeof settings !== "object") return false;
const conversions = (settings as Record<string, unknown>).conversions;
if (!conversions || typeof conversions !== "object") return false;
return (conversions as Record<string, unknown>).report_via_channel === true;
}
/** Lê a chave da organização. LANÇA quando a leitura falha: quem chama espera e tenta de novo. */
export async function lerVendaPeloCanal(
admin: SupabaseClient,
organizationId: string,
): Promise<boolean> {
const { data, error } = await admin
.from("organizations")
.select("settings")
.eq("id", organizationId)
.maybeSingle();
if (error) throw new Error(`leitura da chave falhou: ${error.message}`);
return vendaPeloCanalLigada((data as { settings?: unknown } | null)?.settings);
}