Realizado {money_html(month_data['realised'])} Comprometido {money_html(month_data['committed'])} Provável {money_html(month_data['probable'])} Falta {money_html(management['gap'])}
"""
else:
progress = '
Configura uma meta para visualizar o progresso e o desvio.
'
diagnostics_html = "".join(
f"""
{esc(d.get('severity'))}
{esc(d.get('label'))}
{esc(d.get('detail'))}
"""
for d in forecast.get("diagnostics", [])
) or '
Sem riscos relevantes identificados com os dados atuais.
'
actions_rows = ""
for action in forecast.get("priority_actions", []):
impact = action.get("impact_amount") or 0
flags = []
if action.get("overdue_tasks"):
flags.append(f"{action['overdue_tasks']} task(s) vencida(s)")
if action.get("has_conflict"):
flags.append("conflito de identidade")
actions_rows += f"""
Sem valor realizado para esta métrica no mês selecionado.
'
opportunity_rows = ""
future_valued = [i for i in forecast["items"] if i.get("forecast_class") in {"committed", "probable"} and _number(i.get("amount")) > 0]
for item in future_valued[:80]:
flags = []
if item.get("has_conflict"):
flags.append("conflito fiscal")
if item.get("is_stale"):
flags.append("inativa >30d")
if item.get("overdue_tasks"):
flags.append(f"{item['overdue_tasks']} task(s) vencida(s)")
sample = item.get("probability_sample") or {}
sample_hint = ""
if item.get("probability_source") == "historical_blended":
sample_hint = f" · {int(sample.get('won') or 0)}/{int(sample.get('resolved') or 0)} ganhas"
probability_cell = (
'100%
receita comprometida
'
if item.get("forecast_class") == "committed"
else f"{_pct(item.get('effective_probability'))}
fase {_pct(item.get('probability'))} × atividade {esc(item.get('activity_factor'))}{esc(sample_hint)}
"
for row in forecast.get("stage_summary", [])
)
zero_value_items = [i for i in forecast["items"] if i.get("forecast_class") in {"committed", "probable"} and _number(i.get("amount")) <= 0]
zero_rows = "".join(
f'
Dashboard de gestão comercial. Separa o que já conta para a meta, o que está comprometido e o que ainda depende de conversão. Não representa tesouraria nem substitui validação contabilística.
Período: {esc(period['month_start'])} a {esc(period['month_end'])} · critério: {esc(management['metric_label'])}
{_status_alert(management['status'])}
{kpi_card('Meta mensal', money_html(target_amount), '/forecast', management['metric_label'], 'bi-bullseye')}
{kpi_card('Realizado', money_html(month_data['realised']), '/forecast', f"{summary['realised_count']} registo(s) no mês", 'bi-check2-circle', 'cf-kpi-tone-green')}
{kpi_card('Comprometido', money_html(month_data['committed']), '/forecast', f"{month_data['committed_count']} oportunidade(s) até ao fim do mês", 'bi-lock')}
{kpi_card('Pipeline provável', money_html(month_data['probable']), '/forecast', f"{month_data['probable_count']} oportunidade(s) ponderadas", 'bi-graph-up-arrow')}
{kpi_card('Previsão total', money_html(month_data['forecast_total']), '/forecast', f"cumprimento {_pct(management['attainment'])}", 'bi-speedometer2')}
{kpi_card('Desvio', money_html(management['gap']), '/forecast', 'falta para suportar a meta' if management['gap'] else f"excedente {money_html(management['surplus'])}", 'bi-exclamation-triangle', 'cf-kpi-tone-red' if management['gap'] else 'cf-kpi-tone-green')}
Progresso da meta
Sem dupla contagem entre realizado, comprometido e provável.
Desvio residual{money_html(recoverable.get('residual_gap') or 0)}
Diagnóstico do desvio
{diagnostics_html}
Cenários até ao fim do mês
Conservador
{money_html(scenarios['conservative'])}
Provável
{money_html(scenarios['probable'])}
Com aceleração
{money_html(scenarios['optimistic'])}
Potencial máximo conhecido
{money_html(scenarios.get('maximum_known') or scenarios['optimistic'])}
Novo pipeline necessário
{money_html(management['new_pipeline_required'])}
Conversão usada {_pct(management['new_pipeline_conversion'])} · aproximadamente {esc(management['new_opportunities_required'])} nova(s) oportunidade(s), quando existe valor médio suficiente.
Ações de maior impacto
O que executar hoje para proteger ou recuperar a meta.
Grupo
Oportunidade
Fase
Valor
Ação recomendada
Impacto
{actions_rows}
Realizado no mês
Registos que já contam para a métrica selecionada; não voltam a ser somados no pipeline futuro.
Referência
Valor
Data
{realised_rows}
Oportunidades que suportam a previsão futura
Realizado no mês é apresentado separadamente; esta tabela mostra apenas valor adicional comprometido ou provável.
Oportunidade
Fase
Valor
Probabilidade
Valor esperado
Data
Alertas
{opportunity_rows}
Funil por fase
Quantidade, cobertura e valor.
Fase
Total
Com valor
Bruto
Ponderado
{stage_rows}
Oportunidades por valorizar
{esc(summary['unvalued_opportunities'])} de {esc(summary['opportunities'])} sem valor · cobertura {_pct(summary['value_coverage'])} · qualidade {_pct(summary['quality_score'])}.
Oportunidade
Fase
Atualizada
{zero_rows}
"""
return layout("Meta e desempenho comercial", "Acompanhar vendas e decidir quando mudar a abordagem", body, "forecast")