RFM — regras comparadas
Power BI Gateway · Documento de referência

RFM — as regras, lado a lado

Comparação fato a fato do cálculo de Recência, Frequência, Valor, Nota e Segmento entre as três referências que temos. Documento descritivo — nada foi alterado no backend.

Planilha (VendaMais / “RFM - Erlan.xlsx”) BI do TRON (HorusBI) Nosso gateway (implementação atual)

Estado em jul/2026. Fontes: fórmulas do Excel (aba “Carteira de Clientes”), dado real do BI revertido da tabela T_RFV_027713, e o código RfmScore.php + RfmRepository.php.

01 — Resumo

Veredito rápido

Onde as três concordam, onde divergem, e por quê.

Cada linha é um “fato” do RFM. A última coluna diz a situação do nosso gateway hoje.
FatoPlanilha (Erlan)BI do TRON (dado real)Nosso gatewaySituação
Recência Dias sem compra → 30/60/90/120 Segue 30/60/90/120 (legenda de ≤3d é falsa) 30/60/90/120 bate · 28/29
Frequência Nº de meses c/ compra em 12m Opaco (ETL do DW) Nº de meses c/ compra em 12m só planilha · 15/29
Valor Faixa fixa de R$ (fat. 12m) Opaco (nem quintil, nem faixa) Faixa fixa de R$ — cortes do Erlan decisão aberta · 7/29
F+M médio (FM) ROUNDUP((F+M)/2) (entra no segmento) ROUND((F+V)/2) bate
Nota Não existe soma; saída = segmento R+F+V (3–15) R+F+V (3–15) bate BI
Segmento Matriz 5×5 R × FM 11 segmentos, matriz R × FM Matriz 5×5 R × FM (idêntica à planilha) bate
Janela / população R = histórico · F/M = 12m Estático (pré-calculado no DW) R = histórico · F/V = 12m · população = quem faturou no período alinhado
02 — O achado que muda tudo

A legenda do BI está errada

Legenda na tela ≠ dado no banco

A tela de RFM do BI exibe uma legenda (R5 ≤3 dias, Frequência por “pedidos/semana”, Valor por “quintis 20%”). Mas quando revertemos o dado real da tabela do DW (T_RFV_027713), ele não segue essa legenda.

Prova na Recência — dias reais por score do BI: R5 3–25 · R4 33–54 · R3 61–75 · R2 97–111 · R1 112+. Isso é a régua 30/60/90/120 da planilha, não o “≤3 dias” da legenda.

Por isso a orientação foi: “siga na planilha e veja o quanto bate com o BI — a legenda pode estar errada.” E bateu (28 de 29 clientes na Recência).

03 — Fato a fato

Cada dimensão em detalhe

A régua da planilha, o que o BI faz de verdade, e o que está no nosso gateway.

Recência (R)

Dias desde a última compra (todo o histórico) até hoje.

Planilha R5 ≤30 · R4 31–60 · R3 61–90 · R2 91–120 · R1 >120
BI mesmo comportamento no dado (legenda ≤3/7/14/30 é falsa)
Nosso 30/60/90/120 · 28/29

Frequência (F)

Nº de meses distintos com compra nos últimos 12 meses.

Planilha F5 =12 · F4 9–11 · F3 6–8 · F2 3–5 · F1 ≤2
BI opaco — há F5 sem pedido no ano e cliente com 140+ notas em F2
Nosso igual à planilha · 15/29

F+M médio (FM) — eixo Y da matriz

Média de Frequência e Valor, arredondada pra cima.

Planilha ROUNDUP((F+M)/2)
Nosso ROUND((F+V)/2) — idêntico p/ meios-inteiros · bate

Nota

Pontuação geral do cliente.

Planilha não tem soma 3–15 — a saída é o segmento
BI R+F+V (vai até 15)
Nosso R+F+V · bate BI

Valor (M) — o único ponto em aberto

As três concordam no método: faixa fixa de R$ sobre o faturamento dos últimos 12 meses. Confirmado na planilha: os cortes são números fixos, sem nenhuma função de quintil/percentil/rank. E o Valor do BI não muda quando filtro a data → é estático, não é quintil dinâmico.

Planilha (Erlan) M5 ≥1M · M4 500k–999k · M3 200k–499k · M2 50k–199k · M1 ≤49k
BI do TRON opaco — nem monotônico com faturamento (cliente 000285 = V5 com R$50k; 000682 = V2 com R$365k); quintil bate só 7/41
Nosso (hoje) faixa fixa com os cortes literais do Erlan (1M/500k/200k/50k)

O problema: os cortes do Erlan são de outro cliente. No TRON (fat. 12m de R$10 a ~R$3M, média R$27k) quase todo mundo cai abaixo de R$50k → vira V1. A distribuição atual mostra isso: V1 5427 · V2 565 · V3 566 · V4 462 · V5 565 — o Valor praticamente não separa ninguém.

Decisão pendente (sua): manter o literal do Erlan, ou usar o mesmo método (faixa fixa) com cortes na escala do TRON (≈ 30k/15k/7k/3k, da distribuição real) para o Valor voltar a discriminar. Não mudei nada — só registrei aqui.

04 — Segmentação

A matriz 5×5 (R × F+M)

Idêntica na planilha e no nosso gateway. Eixo X = Recência (1→5), eixo Y = F+M médio (5→1). Campeões exige R5 e FM5 (a versão antiga do nosso doc marcava R5·FM4 como Campeões — está corrigido no código).

R1
R2
R3
R4
R5
FM 5
Não pode
perdê-los
Não pode
perdê-los
Clientes
leais
Clientes
leais
Campeões
FM 4
Em risco
Em risco
Clientes
leais
Clientes
leais
Clientes
leais
FM 3
Em risco
Em risco
Precisam de
atenção
Potenciais
leais
Potenciais
leais
FM 2
Perdidos
Hibernando
Prestes a
dormir
Potenciais
leais
Potenciais
leais
FM 1
Perdidos
Perdidos
Prestes a
dormir
Promissores
Clientes
recentes

→ Recência aumenta para a direita · ↑ Frequência+Valor aumenta para cima

05 — Por que F e V do BI não são reproduzíveis

O que mora no DW e não no Protheus

Recência e Nota do BI batem porque são deriváveis das vendas. Já Frequência e Valor do BI vêm de colunas pré-calculadas na tabela T_RFV_027713 (MySQL do HorusBI), populadas por um ETL fora do Protheus, ao qual não temos acesso. Sinais de que são opacos:

Decisão de projeto (registrada): o gateway define a sua própria versão, calculada do Protheus e responsiva aos filtros (requisito do PO), seguindo a planilha. R e Nota coincidem com o BI; F e V seguem a planilha e por isso divergem dos números do BI — o que é esperado e transparente.

06 — Validação ao vivo

Quanto bate com o BI hoje

Cruzamento por cliente (n = 29) do gateway contra o dado do BID do TRON.

DimensãoAcerto vs BILeitura
Recência28 / 29 (97%)Régua da planilha = dado do BI. ok
NotabateSoma R+F+V, vai até 15. ok
SegmentobateMatriz 5×5 célula a célula. ok
Frequência15 / 29BI opaco; seguimos a planilha. nossa versão
Valor7 / 29BI opaco + cortes do Erlan degeneram no TRON. rever cortes
07 — Extra da planilha

Classificação de Status (ainda não usamos)

A planilha também classifica cada cliente por atividade — pode virar um card/filtro futuro:

StatusRegra (planilha)
Sem compraFaturamento 12m = 0
InativoDias sem compra > 90
Pré-InativoDias sem compra entre 60 e 90
AtivoCaso contrário
08 — Verbatim da planilha

As regras, exatamente como estão no arquivo

Extraído da aba Carteira de Clientes (4.358 clientes) do “RFM - Erlan.xlsx”. Fórmulas literais.

Tabela de faixas (células U:AB)

Um score (5→1) por faixa, em três colunas paralelas — Recência, Frequência, Monetária.
ScoreR — Dias sem compraF — Nº meses c/ compra (12m)M — Fat. últimos 12m (R$)
5≤ 30= 12≥ 1.000.000
431 – 609 – 11500.000 – 999.999,99
361 – 906 – 8200.000 – 499.999,99
291 – 1203 – 550.000 – 199.999,99
1≥ 121≤ 2≤ 49.999,99

Fórmulas (colunas de cálculo)

Dias sem compra = data do relatório − data da última compra
R = faixa de “dias sem compra” → ≤30 = R5 … ≥121 = R1
F = faixa de “nº de meses com compra em 12m”
M = faixa fixa de R$ de “fat. últimos 12 meses” (sem quintil)
Média F+M = ROUNDUP((F + M) / 2)
Status = Fat12=0 → Sem compra · Dias > 90 → Inativo · 60–90 → Pré-Inativo · senão Ativo

Os 11 segmentos (rótulos numerados do arquivo)

Mesma matriz da seção 04, com os nomes exatos e a regra (R, Média F+M):

#SegmentoRegra (R · FM)
01CampeõesR5 · FM5
02Clientes LeaisR3-5 · FM4-5 (exceto R5·FM5)
03Potenciais Clientes LeaisR4-5 · FM2-3
04Clientes RecentesR5 · FM1
05PromissoresR4 · FM1
06Precisam de AtençãoR3 · FM3
07Prestes a DormirR3 · FM1-2
08Em RiscoR1-2 · FM3-4
09Não Pode Perdê-losR1-2 · FM5
10HibernandoR2 · FM2
11PerdidosR1 · FM1-2 · e R2·FM1

Colunas extras que a planilha calcula

Além do RFM: Qtd. de SKUs (36–25m / 24–13m / 12m), Partic. % do faturamento 12m, Comparativo de faturamento de 2 anos com flag Crescendo/Caindo (faturamento e SKUs), Soma de faturamento 36m, Soma de positivação 36m, flags Compraram por janela, e Tipo de Cliente (ex.: Recorrente).

09 — Teste de mesa

Como conferir você mesmo

Três passos, repetíveis em qualquer cliente, para garantir que a régua foi lida certo.

  1. Pegue os 3 insumos do cliente: dias sem compra · nº de meses com compra em 12m · faturamento em 12m.
  2. Aplique a tabela de faixas (seção 08) → R, F, M. Calcule FM = ROUNDUP((F+M)/2) e leia o segmento na matriz (seção 04).
  3. Compare com a planilha (colunas R/F/M/AE/AF), o nosso gateway e o BI.

Exemplo A — na própria planilha (1 por segmento)

Insumos crus → faixas aplicadas na mão → segmento. Bate 100% com as colunas calculadas do arquivo.
Cód.DiasMeses 12mFat. 12mR · F · MFMSegmento (planilha)
85210114.134.6125 · 4 · 5501-Campeões
649114.905.2034 · 4 · 5502-Clientes Leais
833105964.3585 · 2 · 4303-Potenciais Leais
112543229.0465 · 1 · 1104-Clientes Recentes
1251551218.2844 · 1 · 1105-Promissores
15843675903.9853 · 2 · 4306-Precisam de Atenção
23387673143.1273 · 2 · 2207-Prestes a Dormir
1237411441.411.3052 · 2 · 5408-Em Risco
16533992228.8272 · 1 · 3210-Hibernando
10516451331.3971 · 1 · 3211-Perdidos

Exemplo B — no nosso gateway (clientes reais do TRON, hoje)

Mesma conta, insumos vindos do Protheus. R/F/V/Nota conferem com a régua. (V usa os cortes do Erlan — ver seção 03.)
ClienteDiasMeses 12mFat. 12mR · F · VNotaSegmento (gateway)
0092820133.220.2165 · 5 · 515Campeões
0003822810705.5265 · 4 · 413Clientes leais
008687516486.2964 · 3 · 310Potenciais leais
103072641524.9203 · 1 · 48Precisam de atenção
000579113497.6455 · 5 · 313Clientes leais

Reproduzir no gateway (backend, WSL)

Imprime insumos + scores de 10 clientes para conferir na mão — php artisan tinker:

use App\Support\Protheus\RfmScore as S; $fat = App\Support\Protheus\FiltroFaturamento::existsSql('010'); $i12 = "CONVERT(varchar(8),DATEADD(month,-12,GETDATE()),112)"; $rows = DB::connection('protheus')->select(" SELECT TOP 10 cli, DATEDIFF(day,CONVERT(date,ultima,112),CAST(GETDATE() AS date)) dias, meses12, fat12 FROM (SELECT RTRIM(D2_CLIENTE) cli, MAX(D2_EMISSAO) ultima, COUNT(DISTINCT CASE WHEN D2_EMISSAO>=$i12 THEN LEFT(D2_EMISSAO,6) END) meses12, SUM(CASE WHEN D2_EMISSAO>=$i12 THEN D2_VALBRUT ELSE 0 END) fat12 FROM SD2010 D2 WHERE D2.D_E_L_E_T_<>'*' AND $fat GROUP BY RTRIM(D2_CLIENTE)) vc WHERE meses12>=1 ORDER BY fat12 DESC"); foreach ($rows as $x) printf("%s dias=%d m12=%d fat=%s => R%d F%d V%d\n", $x->cli,$x->dias,$x->meses12,number_format($x->fat12), S::recencia($x->dias),S::frequencia($x->meses12),S::valor($x->fat12));

No BI (cruzamento final)

Abra o report da matriz RFM (traz Código + R/F/V por cliente), escolha um cliente e compare: Recência e Nota batem; Frequência e Valor divergem — vêm do ETL do DW, são opacos (esperado, ver seção 05).

Nada foi alterado para produzir este documento — é uma leitura do estado atual (código backend/app/Support/Protheus/RfmScore.php e RfmRepository.php), das fórmulas da planilha “RFM - Erlan.xlsx” e do dado revertido do BI (T_RFV_027713).

Observação: o arquivo backend/docs/regras-metricas.md ainda descreve a versão antiga do RFM (≤3 dias / quintil) — está defasado em relação ao código; a correção dele fica como próximo passo, quando você decidir os cortes do Valor.