Pular para o conteúdo principal

Exemplos Práticos

Exemplos completos de decisões usando DMN no Decision Engine.

Exemplo 1: Aprovação de Crédito Simples

Um exemplo básico que aprova ou nega crédito baseado apenas no score.

DMN

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
id="credit_simple"
name="Simple Credit Decision"
namespace="http://example.com/dmn/credit-simple">

<decision id="creditDecision" name="Credit Decision">
<decisionTable id="creditTable" hitPolicy="FIRST">
<input id="scoreInput" label="Score">
<inputExpression typeRef="number">
<text>score</text>
</inputExpression>
</input>

<output id="resultOutput" name="resultado" typeRef="string"/>

<rule id="rule_denied">
<description>Score muito baixo</description>
<inputEntry><text>&lt; 500</text></inputEntry>
<outputEntry><text>"NEGADO"</text></outputEntry>
</rule>

<rule id="rule_approved">
<description>Score aceitável</description>
<inputEntry><text>&gt;= 500</text></inputEntry>
<outputEntry><text>"APROVADO"</text></outputEntry>
</rule>
</decisionTable>
</decision>

</definitions>

Cenários de Teste

ScoreResultado EsperadoRegra Acionada
400NEGADOrule_denied
500APROVADOrule_approved
720APROVADOrule_approved

Exemplo 2: Financiamento Veicular Completo

Um exemplo real e complexo que avalia financiamento de veículos considerando:

  • Dados do veículo (marca, ano, preço FIPE)
  • Perfil do cliente (score, renda, comprometimento)
  • Marcas premium com condições especiais

DMN Completo

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
id="car_financing"
name="Car Financing Decision"
namespace="http://catalisa.com/dmn/car-financing">

<decision id="financingDecision" name="Financing Decision">
<decisionTable id="financingTable" hitPolicy="FIRST">
<!-- Inputs do Veículo -->
<input id="brandInput" label="Marca">
<inputExpression typeRef="string"><text>marca</text></inputExpression>
</input>
<input id="yearInput" label="Ano">
<inputExpression typeRef="number"><text>anoFabricacao</text></inputExpression>
</input>
<input id="fipeInput" label="Preço FIPE">
<inputExpression typeRef="number"><text>precoFipe</text></inputExpression>
</input>

<!-- Inputs do Cliente -->
<input id="scoreInput" label="Credit Score">
<inputExpression typeRef="number"><text>creditScore</text></inputExpression>
</input>
<input id="incomeInput" label="Renda Mensal">
<inputExpression typeRef="number"><text>rendaMensal</text></inputExpression>
</input>
<input id="debtInput" label="Comprometimento">
<inputExpression typeRef="number"><text>comprometimentoRenda</text></inputExpression>
</input>

<!-- Output: STATUS|TAXA|PARCELAS|ENTRADA|OBSERVACAO -->
<output id="resultOutput" name="resultado" typeRef="string"/>

<!-- ============ REGRAS DE NEGAÇÃO ============ -->

<rule id="rule_denied_score">
<description>Negado - score muito baixo</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&lt; 500</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<outputEntry><text>"NEGADO|0|0|0|Score abaixo do mínimo 500"</text></outputEntry>
</rule>

<rule id="rule_denied_income">
<description>Negado - renda insuficiente</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&lt; 3000</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<outputEntry><text>"NEGADO|0|0|0|Renda mensal abaixo de R$3000"</text></outputEntry>
</rule>

<rule id="rule_denied_debt">
<description>Negado - comprometimento alto</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 0.6</text></inputEntry>
<outputEntry><text>"NEGADO|0|0|0|Comprometimento acima de 60%"</text></outputEntry>
</rule>

<rule id="rule_denied_old_risky">
<description>Negado - veículo antigo com cliente arriscado</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&lt; 2015</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&lt; 650</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<outputEntry><text>"NEGADO|0|0|0|Veiculo antigo para perfil de risco"</text></outputEntry>
</rule>

<!-- ============ REGRAS DE APROVAÇÃO ============ -->

<rule id="rule_approved_premium">
<description>Aprovado Premium - marca premium + cliente excelente</description>
<inputEntry><text>list contains(["BMW", "Mercedes", "Audi", "Porsche", "Volvo", "Land Rover"], marca)</text></inputEntry>
<inputEntry><text>&gt;= 2023</text></inputEntry>
<inputEntry><text>&gt;= 200000</text></inputEntry>
<inputEntry><text>&gt;= 800</text></inputEntry>
<inputEntry><text>&gt;= 20000</text></inputEntry>
<inputEntry><text>&lt; 0.25</text></inputEntry>
<outputEntry><text>"APROVADO_PREMIUM|0.99|72|0.15|Cliente VIP marca premium - taxa 0.99% am"</text></outputEntry>
</rule>

<rule id="rule_approved_excellent">
<description>Aprovado Excelente</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 2020</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 800</text></inputEntry>
<inputEntry><text>&gt;= 10000</text></inputEntry>
<inputEntry><text>&lt; 0.35</text></inputEntry>
<outputEntry><text>"APROVADO|1.19|72|0.15|Excelente perfil - taxa 1.19% am"</text></outputEntry>
</rule>

<rule id="rule_approved_good">
<description>Aprovado Bom</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 2018</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 700</text></inputEntry>
<inputEntry><text>&gt;= 8000</text></inputEntry>
<inputEntry><text>&lt; 0.4</text></inputEntry>
<outputEntry><text>"APROVADO|1.49|60|0.20|Bom perfil - taxa 1.49% am"</text></outputEntry>
</rule>

<rule id="rule_approved_regular">
<description>Aprovado Regular</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 2015</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 600</text></inputEntry>
<inputEntry><text>&gt;= 5000</text></inputEntry>
<inputEntry><text>&lt; 0.5</text></inputEntry>
<outputEntry><text>"APROVADO|1.89|48|0.25|Perfil regular - taxa 1.89% am"</text></outputEntry>
</rule>

<rule id="rule_approved_restricted">
<description>Aprovado com restrição</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 2015</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>&gt;= 500</text></inputEntry>
<inputEntry><text>&gt;= 3000</text></inputEntry>
<inputEntry><text>&lt; 0.6</text></inputEntry>
<outputEntry><text>"APROVADO_RESTRICAO|2.49|36|0.35|Aprovado com restricoes"</text></outputEntry>
</rule>

<!-- ============ FALLBACK ============ -->

<rule id="rule_manual">
<description>Análise manual</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<outputEntry><text>"ANALISE_MANUAL|0|0|0|Requer analise do comite"</text></outputEntry>
</rule>
</decisionTable>
</decision>

</definitions>

Cenários de Teste

Cenário 1: Cliente Premium com BMW

Input:

{
"marca": "BMW",
"anoFabricacao": 2024,
"precoFipe": 450000,
"creditScore": 850,
"rendaMensal": 25000,
"comprometimentoRenda": 0.20
}

Resultado Esperado:

APROVADO_PREMIUM|0.99|72|0.15|Cliente VIP marca premium - taxa 0.99% am

Regra Acionada: rule_approved_premium


Cenário 2: Cliente Bom com Toyota

Input:

{
"marca": "Toyota",
"anoFabricacao": 2022,
"precoFipe": 120000,
"creditScore": 750,
"rendaMensal": 12000,
"comprometimentoRenda": 0.30
}

Resultado Esperado:

APROVADO|1.19|72|0.15|Excelente perfil - taxa 1.19% am

Regra Acionada: rule_approved_excellent


Cenário 3: Cliente Negado - Score Baixo

Input:

{
"marca": "Fiat",
"anoFabricacao": 2020,
"precoFipe": 45000,
"creditScore": 420,
"rendaMensal": 5000,
"comprometimentoRenda": 0.35
}

Resultado Esperado:

NEGADO|0|0|0|Score abaixo do mínimo 500

Regra Acionada: rule_denied_score


Cenário 4: Veículo Antigo + Cliente Arriscado

Input:

{
"marca": "Chevrolet",
"anoFabricacao": 2012,
"precoFipe": 28000,
"creditScore": 520,
"rendaMensal": 4000,
"comprometimentoRenda": 0.55
}

Resultado Esperado:

NEGADO|0|0|0|Veiculo antigo para perfil de risco

Regra Acionada: rule_denied_old_risky


Tabela Completa de Cenários

CenárioMarcaAnoScoreRendaComprom.ResultadoRegra
Premium BMWBMW2024850250000.20APROVADO_PREMIUMrule_approved_premium
Premium MercedesMercedes2024850220000.20APROVADO_PREMIUMrule_approved_premium
Excelente ToyotaToyota2022820150000.25APROVADO (1.19%)rule_approved_excellent
Bom HondaHonda201972090000.38APROVADO (1.49%)rule_approved_good
Regular FiatFiat201865060000.45APROVADO (1.89%)rule_approved_regular
Score BaixoQualquerQualquer42050000.30NEGADOrule_denied_score
Renda BaixaQualquerQualquer70025000.20NEGADOrule_denied_income
Alto Comprom.QualquerQualquer70080000.65NEGADOrule_denied_debt
Antigo+RiscoQualquer201252040000.50NEGADOrule_denied_old_risky

Analisando o Trace

Ao executar uma decisão, o trace mostra exatamente quais regras foram avaliadas e qual foi acionada.

Exemplo de Trace Detalhado

Entrada:

{
"marca": "Toyota",
"anoFabricacao": 2022,
"precoFipe": 120000,
"creditScore": 750,
"rendaMensal": 12000,
"comprometimentoRenda": 0.30
}

Trace:

{
"output": "APROVADO|1.19|72|0.15|Excelente perfil - taxa 1.19% am",
"trace": [
{
"decisionId": "financingDecision",
"decisionName": "Financing Decision",
"outcome": "APROVADO|1.19|72|0.15|Excelente perfil - taxa 1.19% am",
"rulesEvaluated": [
{
"ruleId": "rule_denied_score",
"triggered": false,
"conditions": ["creditScore: 750"],
"outcome": null
},
{
"ruleId": "rule_denied_income",
"triggered": false,
"conditions": ["rendaMensal: 12000"],
"outcome": null
},
{
"ruleId": "rule_denied_debt",
"triggered": false,
"conditions": ["comprometimentoRenda: 0.30"],
"outcome": null
},
{
"ruleId": "rule_denied_old_risky",
"triggered": false,
"conditions": ["anoFabricacao: 2022", "creditScore: 750"],
"outcome": null
},
{
"ruleId": "rule_approved_premium",
"triggered": false,
"conditions": ["marca: Toyota", "..."],
"outcome": null
},
{
"ruleId": "rule_approved_excellent",
"triggered": true,
"conditions": ["anoFabricacao: 2022", "creditScore: 750", "rendaMensal: 12000", "comprometimentoRenda: 0.30"],
"outcome": "APROVADO|1.19|72|0.15|Excelente perfil - taxa 1.19% am"
}
]
}
],
"executionTimeMs": 45,
"versionUsed": "4.0.0"
}

Análise do Trace

Fluxo de avaliação (hitPolicy=FIRST):

1. rule_denied_score → creditScore=750 >= 500 → NÃO acionada
2. rule_denied_income → rendaMensal=12000 >= 3000 → NÃO acionada
3. rule_denied_debt → comprometimento=0.30 < 0.6 → NÃO acionada
4. rule_denied_old_risky → ano=2022 >= 2015 → NÃO acionada
5. rule_approved_premium → marca="Toyota" não está na lista premium → NÃO acionada
6. rule_approved_excellent → TODAS condições OK → ACIONADA ✓

Resultado: APROVADO (1.19% a.m.)

Dicas para Debugging

1. Verifique a Ordem das Regras

Com hitPolicy=FIRST, a ordem importa. Regras de negação devem vir antes das de aprovação.

2. Use o Trace

O trace mostra exatamente por que uma regra foi ou não acionada. Analise as condições de cada regra.

3. Teste Casos Limite

Teste valores nos limites das condições:

  • Score = 499 (negado) vs Score = 500 (aprovado)
  • Comprometimento = 0.59 vs 0.60

4. Verifique list contains

Se usar list contains, certifique-se que:

  • A lista usa colchetes: ["BMW", "Mercedes"]
  • O nome da variável corresponde ao input: marca
  • As strings estão corretas (case-sensitive)
<!-- Correto -->
<inputEntry><text>list contains(["BMW", "Mercedes"], marca)</text></inputEntry>

<!-- Errado (sem colchetes) -->
<inputEntry><text>list contains("BMW", "Mercedes", marca)</text></inputEntry>