#!/usr/bin/env python3 # Painel "Saída de Pauta · Venda" no formato do perfil-lead-site.html (referência aprovada pelo COO) import json from datetime import datetime SP = "/private/tmp/claude-501/-Users-luizh-souza/28aa3f80-7e4d-40f1-9500-a33d868d547f/scratchpad" ref = open(f"{SP}/perfil-lead-site.html", encoding="utf-8").read() dados = json.load(open(f"{SP}/dados.json", encoding="utf-8")) head = ref[ref.index(""): ref.index("") + len("")] head = head.replace("Perfil do Lead · Site · IntelBuzz BI", "Saída de Pauta · Venda · IntelBuzz BI") fmtR = lambda v: ("R$ -" if v < 0 else "R$ ") + f"{abs(round(v)):,}".replace(",", ".") fmtI = lambda v: f"{round(v):,}".replace(",", ".") pct1 = lambda v: str(round(v, 1)).replace(".", ",") + "%" m = dados["mensal"] tot_e = sum(x["e_qtd"] for x in m); tot_ev = sum(x["e_vgv"] for x in m) tot_s = sum(x["s_qtd"] for x in m); tot_sv = sum(x["s_vgv"] for x in m) saldo_v = tot_ev - tot_sv mot = {x["m"]: x for x in dados["motivos"]} vt, vi = mot["Vendido Terceiros"], mot["Vendido Imobiliária"] decid = vt["qtd"] + vi["qtd"] taxa_q = 100 * vi["qtd"] / decid taxa_v = 100 * vi["vgv"] / (vi["vgv"] + vt["vgv"]) MESES = {"2026-05": "Maio", "2026-06": "Junho", "2026-07": "Julho"} CLASSE = {"Vendido Terceiros": ("Perdido", "ruim", "#B23A2E"), "Alugado Terceiros": ("Perdido", "ruim", "#B23A2E"), "Vendido Imobiliária": ("Capturado", "boa", "#2E7D52"), "Alugado Imobiliária": ("Capturado", "boa", "#2E7D52")} jul = next(x for x in dados["captura_mes"] if x["mes"] == "2026-07") semeq = next(x for x in dados["equipes"] if x["eq"] == "Sem equipe") susp = mot["Suspenso"] def pill(v, boa=50, neutra=25): cls = "boa" if v >= boa else ("neutra" if v >= neutra else "ruim") return f"{pct1(v)}" def saldo_pill(v): cls = "boa" if v >= 0 else "ruim" return f"{fmtR(v)}" # ── Nº 01 Balanço mensal ── tb1 = "MêsEntradasVGV entradaSaídasVGV saídaSaldo de VGV" for x in m: sv = x["e_vgv"] - x["s_vgv"] tb1 += (f"{MESES[x['mes']]}{x['e_qtd']}" f"{fmtR(x['e_vgv'])}{x['s_qtd']}" f"{fmtR(x['s_vgv'])}{saldo_pill(sv)}") tb1 += (f"Trimestre{tot_e}{fmtR(tot_ev)}" f"{tot_s}{fmtR(tot_sv)}{saldo_pill(saldo_v)}") # ── Nº 02 Captura ── tb2 = "MêsBuzz sobre decididasCaptura por imóveisCaptura por VGV" for x in dados["captura_mes"]: dq = x["vi"] + x["vt"]; dv = x["vi_vgv"] + x["vt_vgv"] tb2 += (f"{MESES[x['mes']]}{x['vi']}" f" de {dq}" f"{pill(100*x['vi']/dq)}{pill(100*x['vi_vgv']/dv)}") tb2 += (f"Trimestre{vi['qtd']} de {decid}" f"{pill(taxa_q)}{pill(taxa_v)}") # ── Nº 03 Motivos ── max_share_m = max(100 * (x["vgv"] or 0) / tot_sv for x in dados["motivos"]) tb3 = "MotivoShare do VGV de saídaImóveisVGVClasse" for x in sorted(dados["motivos"], key=lambda r: -(r["vgv"] or 0)): share = 100 * (x["vgv"] or 0) / tot_sv nome_cls, pcls, cor = CLASSE.get(x["m"], ("Neutro", "neutra", "#8A8D8E")) apagado = " apagado" if x["m"] in ("Voltou para pauta", "(em apuração)") else "" tb3 += (f"{x['m']}" f"
" f"{pct1(share)}
" f"{x['qtd']}{fmtR(x['vgv'] or 0)}" f"{nome_cls}") # ── Nº 04 Equipes ── eqs = [x for x in dados["equipes"]] max_share_e = max(max(100*x["e_vgv"]/tot_ev, 100*x["s_vgv"]/tot_sv) for x in eqs) tb4 = "EquipeShare do VGV ent/saiEntradas / SaídasVGV entradaVGV saídaSaldo" for x in sorted(eqs, key=lambda r: -r["s_vgv"]): se, ss = 100 * x["e_vgv"] / tot_ev, 100 * x["s_vgv"] / tot_sv tb4 += (f"{x['eq']}" f"
" f"
{pct1(se)}
" f"
{pct1(ss)}
" f"
" f"{x['e_qtd']}/{x['s_qtd']}" f"{fmtR(x['e_vgv'])}{fmtR(x['s_vgv'])}" f"{saldo_pill(x['e_vgv'] - x['s_vgv'])}") # ── Nº 05 Corretores (merge entrada+saída, top por saída) ── corr = {} for x in dados["corr_ent"]: corr.setdefault(x["nome"], {"e_qtd": 0, "e_vgv": 0, "s_qtd": 0, "s_vgv": 0}) corr[x["nome"]]["e_qtd"] += x["qtd"]; corr[x["nome"]]["e_vgv"] += x["vgv"] or 0 for x in dados["corr_sai"]: corr.setdefault(x["nome"], {"e_qtd": 0, "e_vgv": 0, "s_qtd": 0, "s_vgv": 0}) corr[x["nome"]]["s_qtd"] += x["qtd"]; corr[x["nome"]]["s_vgv"] += x["vgv"] or 0 rank = sorted(corr.items(), key=lambda kv: -kv[1]["s_vgv"]) top, resto = rank[:14], rank[14:] max_share_c = max(100 * v["s_vgv"] / tot_sv for _, v in top) tb5 = "CorretorShare do VGV de saídaEntradas / SaídasVGV entradaVGV saídaSaldo" def linha_corr(nome, v, apagado=""): ss = 100 * v["s_vgv"] / tot_sv return (f"{nome}" f"
{pct1(ss)}
" f"{v['e_qtd']}/{v['s_qtd']}" f"{fmtR(v['e_vgv'])}{fmtR(v['s_vgv'])}" f"{saldo_pill(v['e_vgv'] - v['s_vgv'])}") for nome, v in top: tb5 += linha_corr(nome, v) outros = {"e_qtd": sum(v["e_qtd"] for _, v in resto), "e_vgv": sum(v["e_vgv"] for _, v in resto), "s_qtd": sum(v["s_qtd"] for _, v in resto), "s_vgv": sum(v["s_vgv"] for _, v in resto)} tb5 += linha_corr(f"Outros ({len(resto)} corretores)", outros, "apagado") # ── Nº 06 Imóveis perdidos ── tb6 = "CódigoBairroAgenciadorSaiu emValor" for i, p in enumerate(dados["perd_top"], 1): dia = "/".join(reversed(p["dia"].split("-")[1:])) + "" dia = p["dia"][8:10] + "/" + p["dia"][5:7] tb6 += (f"{i}º{p['codigo']}" f"{p['bairro'] or 'Sem bairro'}{p['nome'] or 'Não informado'}" f"{dia}{fmtR(p['vgv'])}") gerado = datetime.now().strftime("%d/%m/%Y %H:%M") body = f"""
Buzz iIntelBuzz · BI
Saída de Pauta · Venda
Recorte
Maio a Julho de 2026
Fonte: Vista Tracker · eventos de entrada e baixa da pauta de venda · base corrigida do rótulo "Voltou para pauta" Gerado em {gerado}
01Imóveis: entrou x saiuTrimestre
416 → 348
416 imóveis entraram na pauta e 348 saírampauta cresceu +68
02Valor: entrou x saiuTrimestre
{fmtR(saldo_v)}
Entrou {fmtR(tot_ev)} e saiu {fmtR(tot_sv)}carteira perdeu 3,1%
03O mercado vendeu no nosso lugarPerda
203 imóveis
{fmtR(vt['vgv'])} vendidos por concorrente ou pelo dono57,5% de tudo que saiu
04Quando vende, quem vende?Captura
{pct1(taxa_q)} Buzz
De {decid} imóveis da pauta que foram vendidos, a Buzz vendeu {vi['qtd']}piorando: julho {pct1(100*jul['vi']/(jul['vi']+jul['vt']))}
"A pauta cresceu 68 imóveis no trimestre. Então por que o valor da carteira está caindo?"
Porque o mercado está vendendo o que a Buzz capta. Entraram {fmtR(tot_ev)} e saíram {fmtR(tot_sv)}: de cada R$ 100 que saíram, {pct1(100*vt['vgv']/tot_sv).replace('%','')} foram imóveis vendidos por terceiros. A Buzz disputou {decid} vendas decididas dentro da própria pauta e ganhou {vi['qtd']} ({pct1(taxa_q)}). A reposição segura a quantidade, não segura o valor.
O balanço mês a mêsEntradas, saídas e captura por mês

Balanço mensaleventos com valor de venda

{tb1}

Captura nas vendas decididasVendido Imobiliária sobre Imobiliária + Terceiros

{tb2}

Suspensos e demais baixas ficam fora da conta porque não são disputa de venda. Régua do painel /buzz-vista: verde acima de 50%, cinza entre 25% e 50%, vermelho abaixo de 25%.

Por onde o valor saiMotivo da baixa e responsabilidade por equipe
EntradasSaídasShare = % do VGV total de entrada ou de saída do trimestre

Motivos da saídastatus real do imóvel após a baixa

{tb3}

Entrada e saída por equipeordenado por VGV de saída

{tb4}
Quem move a pautaCorretores e os imóveis de maior valor perdidos

Corretorestop 14 por VGV de saída · entradas na mesma linha

{tb5}

Maiores imóveis perdidos para terceirostop 15 do trimestre

{tb6}
MétodoRéguas e correção da base

Como este painel foi montado

  • Entradas são eventos de novo agenciamento ou novo cadastro com valor de venda no Vista Tracker. Saídas são baixas da pauta de venda. Eventos revertidos pela reconciliação não entram. O histórico do tracker inicia em 11/05/2026, limitação que afeta o começo de maio.
  • Motivo da saída vem do status real do imóvel no Vista após a baixa (via warehouse). "Suspenso" e "(em apuração)" não têm motivo declarado pelo corretor; a declaração estruturada é a fila do CRM em crm.intelbuzz.com.br/saidas.
  • Correção de 10/08/2026: o rótulo "Voltou para pauta" era atribuído por engano quando o warehouse (atrasado um dia) ainda mostrava o imóvel ativo. Das 111 ocorrências históricas, 107 eram falsas e foram reclassificadas com o motivo real. Versões anteriores deste relatório subestimavam a perda para terceiros.
  • Sem equipe: imóvel cujo agenciador não está mapeado em nenhuma equipe no cadastro de equipes do tracker.
""" html = "\n\n" + head + "\n\n" + body open(f"{SP}/painel_pauta2.html", "w", encoding="utf-8").write(html) print("ok", len(html))