# Projeção de Vendas Baseada em META - Documentação Técnica

## 1. Resumo Executivo

Sistema de projeção de vendas que calcula quanto será vendido até o final do mês/ano baseado em:
- Venda realizada até hoje (MTD/YTD)
- Meta do período
- Dias úteis, fins de semana e feriados restantes
- Pesos diferenciados por tipo de dia

**Resultado final:** percentual projetado vs meta com indicador de risco (verde/amarelo/vermelho).

---

## 2. Fórmulas Matemáticas

### 2.1 Dias Ponderados Total do Período

```
dias_ponderados_total = (uteis * P_UTIL) + (fds * P_FDS) + (feriados * P_FERIADO)
```

**Onde:**
- `uteis` = quantidade de dias úteis (segunda a sexta)
- `fds` = quantidade de finais de semana (sábado/domingo)
- `feriados` = quantidade de feriados
- `P_UTIL` = 1.00 (peso padrão para dia útil)
- `P_FDS` = 1.25 (peso padrão para fim de semana, produtividade 25% maior)
- `P_FERIADO` = 1.35 (peso padrão para feriado, produtividade 35% maior)

**Exemplo:**
```
Janeiro 2026:
- Dias úteis: 22
- Fins de semana: 8
- Feriados: 1

dias_ponderados_total = (22 * 1.00) + (8 * 1.25) + (1 * 1.35)
                      = 22 + 10 + 1.35
                      = 33.35 dias equivalentes
```

### 2.2 Meta Diária Equivalente

```
meta_diaria_equiv = meta_mes / dias_ponderados_total
```

**Exemplo:**
```
meta_mes = R$ 100.000,00
meta_diaria_equiv = 100.000 / 33.35 = R$ 2.999,25 por dia equivalente
```

### 2.3 Dias Ponderados Restantes

```
dias_ponderados_restantes = (uteis_restantes * P_UTIL) + (fds_restantes * P_FDS) + (feriados_restantes * P_FERIADO)
```

**Exemplo (considerando 22 de janeiro):**
```
- Dias úteis restantes: 1 (apenas 23, 24, 27, 28, 29, 30, 31 = 4 dias)
- Fins de semana restantes: 2 (25-26 e último fim de semana)
- Feriados restantes: 0

dias_ponderados_restantes = (4 * 1.00) + (2 * 1.25) + (0 * 1.35)
                          = 4 + 2.5 + 0
                          = 6.5 dias equivalentes
```

### 2.4 Projeção de Fechamento

```
proj_fechamento = realizado_mtd + (meta_diaria_equiv * dias_ponderados_restantes)
```

**Exemplo:**
```
realizado_mtd = R$ 45.000,00
proj_fechamento = 45.000 + (2.999,25 * 6.5)
                = 45.000 + 19.495,13
                = R$ 64.495,13
```

### 2.5 Percentual Projetado vs Meta

```
proj_perc = proj_fechamento / meta_mes
```

**Exemplo:**
```
proj_perc = 64.495,13 / 100.000
          = 0.6450 = 64,50%
```

### 2.6 Classificação de Risco

| Percentual | Status   | Cor      | Emoji |
|-----------|----------|----------|-------|
| ≥ 100%    | OK       | Verde    | 🟢    |
| 95-99.9%  | Alerta   | Amarelo  | 🟡    |
| < 95%     | Risco    | Vermelho | 🔴    |

---

## 3. Implementação PHP

### 3.1 Classe Principal: `ProjecaoVendas`

**Localização:** `app/classes/ProjecaoVendas.php`

**Métodos:**
- `ProjecaoVendas::projetarMes()` - Calcula projeção do mês
- `ProjecaoVendas::projetarAno()` - Calcula projeção do ano
- `ProjecaoVendas::obterCorHex()` - Retorna cor HEX
- `ProjecaoVendas::obterStatus()` - Retorna status textual

### 3.2 Uso Básico

```php
require_once(__DIR__ . '/app/classes/ProjecaoVendas.php');

$resultado = ProjecaoVendas::projetarMes(
    realizadoMTD: 45000.00,
    metaMes: 100000.00,
    uteisMes: 22,
    fdsMes: 8,
    feriadosMes: 1,
    uteisRestantes: 4,
    fdsRestantes: 2,
    feriadosRestantes: 0
);

echo "Projeção: R$ " . number_format($resultado['proj_fechamento_mes'], 2);
echo "Status: " . $resultado['status'];
echo "Cor: " . $resultado['cor'];
```

**Retorno:**
```php
Array (
    [proj_fechamento_mes] => 64495.13
    [proj_perc_mes] => 0.6450
    [cor] => text-danger
    [dias_ponderados_total] => 33.35
    [dias_ponderados_restantes] => 6.5
    [meta_diaria_equiv] => 2999.25
    [status] => risco
    [realizado_mtd] => 45000
    [meta_mes] => 100000
)
```

### 3.3 Com Pesos Customizados

```php
$resultado = ProjecaoVendas::projetarMes(
    realizadoMTD: 45000.00,
    metaMes: 100000.00,
    uteisMes: 22,
    fdsMes: 8,
    feriadosMes: 1,
    uteisRestantes: 4,
    fdsRestantes: 2,
    feriadosRestantes: 0,
    pesos: [
        'util' => 1.10,      // Dias úteis valem 10% mais
        'fds' => 1.40,       // Fins de semana valem 40% mais
        'feriado' => 0.80    // Feriados valem 20% menos
    ]
);
```

---

## 4. Integração no Dashboard Existente

### 4.1 Em `home_service.php`

Adicione após a função `obterDadosDashboard()`:

```php
<?php
// Adicione em home_service.php

require_once(__DIR__ . '/../classes/ProjecaoVendas.php');
require_once(__DIR__ . '/../classes/ProjecaoVendas_Helpers.php');

/**
 * Enriquece o array de KPI com dados de projeção
 */
function enriquecerKPIsComProjecao(
    array &$kpiVariaveis,
    PDO $pdo,
    int $mesAtual,
    int $anoAtual
) {
    foreach ($kpiVariaveis as &$kpi) {
        $projecao = calcularProjecaoVariavel(
            $pdo,
            $kpi,
            $mesAtual,
            $anoAtual
        );
        
        $kpi['projecao_mes'] = $projecao;
    }
}

// Uso em home.php:
$kpisVariaveis = obterDadosDashboard($pdo, $cdempresa, $anoref, ...);
enriquecerKPIsComProjecao($kpisVariaveis, $pdo, $mesAtual, $anoAtual);

// Agora cada KPI tem $kpi['projecao_mes'] com os dados de projeção
?>
```

### 4.2 Em `home.php` (Template)

Adicione no card de KPI:

```html
<?php foreach ($kpisVariaveis as $kpi): ?>
    <div class="kpi-card">
        <h4><?= $kpi['nome'] ?></h4>
        
        <!-- Dados Atuais -->
        <div class="kpi-row">
            <label>Realizado:</label>
            <value><?= formatarValorDashboard($kpi['realMes']) ?></value>
        </div>
        <div class="kpi-row">
            <label>Meta:</label>
            <value><?= formatarValorDashboard($kpi['orcMes']) ?></value>
        </div>
        
        <!-- Projeção -->
        <div class="kpi-row projecao">
            <label>Projeção:</label>
            <value class="<?= $kpi['projecao_mes']['cor'] ?>">
                <?= formatarValorDashboard($kpi['projecao_mes']['proj_fechamento_mes']) ?>
            </value>
        </div>
        
        <!-- Percentual Projetado -->
        <div class="kpi-row percentual">
            <label>% Projetado:</label>
            <value class="<?= $kpi['projecao_mes']['cor'] ?>">
                <?= round($kpi['projecao_mes']['proj_perc_mes'] * 100, 1) ?>%
            </value>
        </div>
        
        <!-- Status -->
        <div class="kpi-status">
            <span class="badge <?= $kpi['projecao_mes']['status'] === 'ok' ? 'bg-success' : ($kpi['projecao_mes']['status'] === 'alerta' ? 'bg-warning' : 'bg-danger') ?>">
                <?= ucfirst($kpi['projecao_mes']['status']) ?>
            </span>
        </div>
        
        <!-- Info de Calendário -->
        <div class="kpi-calendar-info small text-muted">
            <p>Meta diária: R$ <?= number_format($kpi['projecao_mes']['meta_diaria_equiv'], 2) ?></p>
            <p>Dias ponderados restantes: <?= round($kpi['projecao_mes']['dias_ponderados_restantes'], 2) ?></p>
        </div>
    </div>
<?php endforeach; ?>
```

---

## 5. Banco de Dados

### 5.1 Tabela de Feriados (Opcional)

Se você quer automatizar feriados:

```sql
CREATE TABLE `back`.`feriados` (
    `id` INT AUTO_INCREMENT PRIMARY KEY,
    `data_feriado` DATE NOT NULL,
    `nome_feriado` VARCHAR(100) NOT NULL,
    `pais` VARCHAR(2) DEFAULT 'BR',
    `tipo` ENUM('federal', 'estadual', 'municipal', 'empresa') DEFAULT 'federal',
    `criado_em` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY `uk_data_pais` (`data_feriado`, `pais`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- Feriados 2026 Brasil
INSERT INTO `back`.`feriados` (`data_feriado`, `nome_feriado`) VALUES
('2026-01-01', 'Ano Novo'),
('2026-02-17', 'Carnaval'),
('2026-04-21', 'Tiradentes'),
('2026-05-01', 'Dia do Trabalho'),
('2026-09-07', 'Independência'),
('2026-10-12', 'Nossa Senhora Aparecida'),
('2026-11-02', 'Finados'),
('2026-11-20', 'Consciência Negra'),
('2026-12-25', 'Natal');
```

### 5.2 Query para Obter Calendário do Mês

```sql
SELECT 
    MONTH(data_feriado) as mes,
    YEAR(data_feriado) as ano,
    SUM(CASE WHEN DAYOFWEEK(data_feriado) BETWEEN 2 AND 6 THEN 1 ELSE 0 END) as feriados_uteis,
    SUM(CASE WHEN DAYOFWEEK(data_feriado) IN (1, 7) THEN 1 ELSE 0 END) as feriados_fds
FROM back.feriados
WHERE YEAR(data_feriado) = 2026
  AND MONTH(data_feriado) = 1
GROUP BY mes, ano;
```

---

## 6. Exemplos de Uso em Diferentes Cenários

### 6.1 Varejo - Loja Física

```php
$projecao = ProjecaoVendas::projetarMes(
    realizadoMTD: 8500.00,      // Vendas até hoje
    metaMes: 25000.00,          // Meta mensal
    uteisMes: 20,               // Dias úteis (seg-sex)
    fdsMes: 8,                  // Sábados/domingos (abertos)
    feriadosMes: 1,             // Feriados (fechada)
    uteisRestantes: 5,
    fdsRestantes: 2,
    feriadosRestantes: 0,
    pesos: [
        'util' => 0.95,         // Dias úteis menos produtivos
        'fds' => 1.50,          // Fins de semana são TOP! (+50%)
        'feriado' => 0.00       // Fechada no feriado
    ]
);
```

### 6.2 Serviços B2B

```php
$projecao = ProjecaoVendas::projetarMes(
    realizadoMTD: 120000.00,
    metaMes: 300000.00,
    uteisMes: 21,
    fdsMes: 8,
    feriadosMes: 0,             // Feriados não afetam serviço
    uteisRestantes: 3,
    fdsRestantes: 2,
    feriadosRestantes: 0,
    pesos: [
        'util' => 1.20,         // Dias úteis muito produtivos (+20%)
        'fds' => 0.50,          // Fins de semana com apenas 50%
        'feriado' => 0.20       // Alguns atendimentos mesmo em feriado
    ]
);
```

### 6.3 SaaS / Assinatura

```php
$projecao = ProjecaoVendas::projetarMes(
    realizadoMTD: 50000.00,
    metaMes: 100000.00,
    uteisMes: 21,
    fdsMes: 8,
    feriadosMes: 0,
    uteisRestantes: 5,
    fdsRestantes: 2,
    feriadosRestantes: 0,
    pesos: [
        'util' => 1.00,         // Todos os dias iguais
        'fds' => 1.00,          // (SaaS opera 24/7)
        'feriado' => 1.00
    ]
);
```

---

## 7. Cálculo de Dias Úteis Programaticamente

Se você não tem tabela de calendário/feriados:

```php
function calcularDiasUteisMes(int $mes, int $ano, array $feriadosData = []): array {
    $diasTotal = cal_days_in_month(CAL_GREGORIAN, $mes, $ano);
    
    $uteis = 0;
    $fds = 0;
    $feriados = 0;
    
    for ($dia = 1; $dia <= $diasTotal; $dia++) {
        $timestamp = mktime(0, 0, 0, $mes, $dia, $ano);
        $dayOfWeek = date('w', $timestamp); // 0=dom, 6=sab
        $dataStr = date('Y-m-d', $timestamp);
        
        if (in_array($dataStr, $feriadosData)) {
            $feriados++;
        } elseif ($dayOfWeek == 0 || $dayOfWeek == 6) {
            $fds++;
        } else {
            $uteis++;
        }
    }
    
    return [
        'uteis' => $uteis,
        'fds' => $fds,
        'feriados' => $feriados,
    ];
}

// Uso:
$calendario = calcularDiasUteisMes(1, 2026, [
    '2026-01-01',  // Ano Novo
    '2026-02-17',  // Carnaval
]);

// Resultado: [uteis => 22, fds => 8, feriados => 1]
```

---

## 8. Gráficos

### 8.1 Gráfico de Linha (Chart.js)

```javascript
const chartProjecao = {
    type: 'line',
    data: {
        labels: ['Hoje', 'Projeção'],
        datasets: [
            {
                label: 'Realizado',
                data: [45000, 45000],
                borderColor: '#16a34a',
                fill: false
            },
            {
                label: 'Projeção',
                data: [45000, 64495],
                borderColor: '#dc2626',
                borderDash: [5, 5],
                fill: false,
                tension: 0.4
            },
            {
                label: 'Meta',
                data: [100000, 100000],
                borderColor: '#6b7280',
                fill: false
            }
        ]
    }
};
```

### 8.2 Indicador Simples

```html
<div class="projecao-indicator">
    <div class="valor"><?= formatarValor($proj['proj_fechamento_mes']) ?></div>
    <div class="percentual <?= $proj['cor'] ?>">
        <?= round($proj['proj_perc_mes'] * 100, 1) ?>%
    </div>
    <div class="status <?= $proj['status'] ?>">
        <?= strtoupper($proj['status']) ?>
    </div>
</div>
```

---

## 9. Casos de Uso Avançados

### 9.1 Múltiplas Variáveis com Agregação

```php
$projecoesMes = [];
$totalRealizado = 0;
$totalMeta = 0;
$totalProjetado = 0;

foreach ($kpisVariaveis as $kpi) {
    $proj = ProjecaoVendas::projetarMes(...);
    $projecoesMes[] = $proj;
    
    $totalRealizado += $proj['realizado_mtd'];
    $totalMeta += $proj['meta_mes'];
    $totalProjetado += $proj['proj_fechamento_mes'];
}

$projecaoAgregada = [
    'proj_fechamento' => $totalProjetado,
    'proj_perc' => $totalMeta > 0 ? ($totalProjetado / $totalMeta) : 0,
];
```

### 9.2 Projeção por Período (Semana/Quinzena)

Você pode calcular dinâmicamente para qualquer período, não apenas mês inteiro:

```php
// Projeção até próxima sexta
$projSemana = ProjecaoVendas::projetarMes(
    realizadoMTD: $realizado,
    metaMes: ($metaMes / 4.3),  // Meta "por semana"
    uteisMes: 5,                 // 1 semana = 5 dias úteis
    fdsMes: 1,
    feriadosMes: 0,
    uteisRestantes: 3,           // até sexta
    fdsRestantes: 1,
    feriadosRestantes: 0
);
```

---

## 10. Parametrização de Pesos

Você pode criar uma tabela para armazenar pesos por tipo de negócio:

```sql
CREATE TABLE `back`.`config_pesos_projecao` (
    `id` INT AUTO_INCREMENT PRIMARY KEY,
    `tipo_negocio` VARCHAR(50) NOT NULL,
    `peso_util` DECIMAL(4,2) DEFAULT 1.00,
    `peso_fds` DECIMAL(4,2) DEFAULT 1.25,
    `peso_feriado` DECIMAL(4,2) DEFAULT 1.35,
    `ativo` TINYINT DEFAULT 1,
    UNIQUE KEY `uk_tipo` (`tipo_negocio`)
);

INSERT INTO `back`.`config_pesos_projecao` VALUES
(NULL, 'varejo', 0.95, 1.50, 0.00, 1),
(NULL, 'b2b', 1.20, 0.50, 0.20, 1),
(NULL, 'saas', 1.00, 1.00, 1.00, 1);
```

---

## 11. Checklist de Implementação

- [ ] Copiar `ProjecaoVendas.php` para `app/classes/`
- [ ] Copiar `ProjecaoVendas_Helpers.php` para `app/classes/`
- [ ] (Opcional) Criar tabela `feriados` no banco
- [ ] (Opcional) Criar tabela `config_pesos_projecao`
- [ ] Adicionar função em `home_service.php`
- [ ] Atualizar template em `home.php`
- [ ] Testar com dados reais
- [ ] Ajustar pesos conforme sua realidade de negócio
- [ ] Validar com stakeholders

---

## 12. Troubleshooting

| Problema | Causa | Solução |
|----------|-------|---------|
| Projeção muito alta | Pesos muito altos | Reduzir P_FDS e P_FERIADO |
| Projeção muito baixa | Pesos muito baixos | Aumentar P_UTIL |
| Dados de feriado errados | Tabela não alimentada | Executar INSERT dos feriados |
| Status sempre "risco" | Meta muito alta | Ajustar meta ou revisar pesos |

---

## 13. Referências e Extensões

- Adicionar análise de sazonalidade (vendas maiores em alguns meses)
- Machine learning para ajustar pesos automaticamente
- Projeções por categoria/produto/vendedor
- Alertas automáticos quando projeção cair abaixo de limiares

---

**Versão:** 1.0  
**Última atualização:** 2026-01-22  
**Autor:** BI Team  
