> ## Documentation Index
> Fetch the complete documentation index at: https://developers.uvvipague.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Débitos Dependentes, Distintos e Obrigatórios

> Entenda as regras de relacionamento entre débitos veiculares e como tratá-las corretamente

## Introdução

Ao consultar débitos veiculares, é comum encontrar situações onde alguns débitos possuem **relacionamentos e restrições** entre si. A API Uvvipague retorna três tipos de relacionamentos que você precisa entender e tratar corretamente:

<CardGroup cols={3}>
  <Card title="Dependentes" icon="link">
    Débitos que devem ser pagos juntos
  </Card>

  <Card title="Distintos" icon="ban">
    Débitos que não podem ser pagos juntos
  </Card>

  <Card title="Obrigatórios" icon="shield-check">
    Débitos que sempre devem ser incluídos
  </Card>
</CardGroup>

<Warning>
  **Importante**: Ignorar essas regras resultará em erro na solicitação de pagamento. É fundamental validar esses relacionamentos antes de processar o pagamento.
</Warning>

## Débitos Dependentes (dependsOn)

### O que são?

Débitos dependentes são aqueles que **precisam ser pagos em conjunto**. Quando um débito possui dependência de outro, ambos devem ser incluídos na mesma solicitação de pagamento.

### Exemplo Comum

O caso mais comum é o **licenciamento**, que geralmente depende da quitação do IPVA e/ou multas pendentes.

<Info>
  **Regra**: Para licenciar um veículo, é necessário estar com o IPVA e multas em dia. Por isso, o débito de licenciamento pode ter dependência desses outros débitos.
</Info>

### Estrutura da Resposta

Cada débito retornado pela API possui um campo `dependsOn` que é um array contendo os IDs dos débitos dos quais ele depende:

```json theme={null}
{
  "debts": [
    {
      "id": "17BD43F1-E345-4A43-BFFF-0952CA7A3FAB",
      "amount": 206.86,
      "title": "Infração a Vencer",
      "description": "Infração de Trânsito - Auto: 5B3022271 - Guia: 173622147",
      "dueDate": "2022-04-18T00:00:00",
      "type": "ticket",
      "required": false,
      "dependsOn": [],
      "distinct": []
    },
    {
      "id": "B8E1F87B-E2A7-483B-8BAF-977291B2A3CC",
      "amount": 144.86,
      "title": "Licenciamento",
      "description": "Licenciamento 2024",
      "type": "licensing",
      "year": 2024,
      "required": false,
      "dependsOn": [
        "17BD43F1-E345-4A43-BFFF-0952CA7A3FAB"
      ],
      "distinct": []
    }
  ]
}
```

No exemplo acima:

* O débito de **Licenciamento** (`B8E1F87B-...`) depende da **Infração** (`17BD43F1-...`)
* Para pagar o licenciamento, você **deve** incluir a infração na mesma solicitação

### Como Validar

Antes de enviar a solicitação de pagamento, valide se todos os débitos dependentes estão incluídos:

<CodeGroup>
  ```javascript JavaScript theme={null}
  function validarDebitos(debitosSelecionados, todosDebitos) {
    for (const debito of debitosSelecionados) {
      // Verifica se o débito tem dependências
      if (debito.dependsOn && debito.dependsOn.length > 0) {
        // Verifica se todas as dependências estão selecionadas
        for (const dependenciaId of debito.dependsOn) {
          const dependenciaIncluida = debitosSelecionados.some(
            d => d.id === dependenciaId
          );
          
          if (!dependenciaIncluida) {
            const dependencia = todosDebitos.find(d => d.id === dependenciaId);
            throw new Error(
              `O débito "${debito.title}" depende de "${dependencia.title}" ` +
              `e ambos devem ser pagos juntos.`
            );
          }
        }
      }
    }
    
    return true;
  }

  // Exemplo de uso
  try {
    validarDebitos(debitosSelecionados, todosDebitos);
    // Prosseguir com o pagamento
  } catch (error) {
    console.error(error.message);
    // Exibir mensagem ao usuário
  }
  ```

  ```python Python theme={null}
  def validar_debitos(debitos_selecionados, todos_debitos):
      """
      Valida se todos os débitos dependentes estão incluídos
      """
      for debito in debitos_selecionados:
          # Verifica se o débito tem dependências
          if debito.get('dependsOn') and len(debito['dependsOn']) > 0:
              # Verifica se todas as dependências estão selecionadas
              for dependencia_id in debito['dependsOn']:
                  dependencia_incluida = any(
                      d['id'] == dependencia_id 
                      for d in debitos_selecionados
                  )
                  
                  if not dependencia_incluida:
                      dependencia = next(
                          d for d in todos_debitos 
                          if d['id'] == dependencia_id
                      )
                      raise ValueError(
                          f"O débito '{debito['title']}' depende de "
                          f"'{dependencia['title']}' e ambos devem ser pagos juntos."
                      )
      
      return True

  # Exemplo de uso
  try:
      validar_debitos(debitos_selecionados, todos_debitos)
      # Prosseguir com o pagamento
  except ValueError as error:
      print(error)
      # Exibir mensagem ao usuário
  ```
</CodeGroup>

### Erro ao Não Respeitar Dependências

Se você tentar pagar um débito sem incluir suas dependências, a API retornará um erro:

```json theme={null}
{
  "error": {
    "code": "DEPENDENT_DEBTS_MISSING",
    "message": "Existem débitos dependentes que devem ser pagos juntos ao débito informado",
    "details": {
      "missingDebts": [
        {
          "id": "17BD43F1-E345-4A43-BFFF-0952CA7A3FAB",
          "title": "Infração a Vencer"
        }
      ]
    }
  }
}
```

## Débitos Distintos (distinct)

### O que são?

Débitos distintos são aqueles que **não podem ser pagos juntos na mesma transação**. Eles são mutuamente exclusivos.

### Exemplo Comum

O caso mais comum é quando o IPVA possui duas opções de pagamento:

* **Cota Única** (com desconto)
* **Cotas Parceladas** (sem desconto)

Você deve escolher **apenas uma** dessas opções, não pode pagar ambas.

<Warning>
  **Atenção**: Tentar pagar débitos distintos juntos resultará em erro. O usuário deve escolher qual opção deseja.
</Warning>

### Estrutura da Resposta

Cada débito possui um campo `distinct` que é um array contendo os IDs dos débitos que não podem ser pagos junto com ele:

```json theme={null}
{
  "debts": [
    {
      "id": "A1B2C3D4-1234-5678-90AB-CDEF12345678",
      "amount": 1500.00,
      "title": "IPVA 2024 - Cota Única",
      "description": "IPVA 2024 em cota única com 3% de desconto",
      "type": "ipva",
      "year": 2024,
      "hasDiscount": true,
      "required": false,
      "dependsOn": [],
      "distinct": [
        "E5F6G7H8-9012-3456-78IJ-KLMN90123456"
      ]
    },
    {
      "id": "E5F6G7H8-9012-3456-78IJ-KLMN90123456",
      "amount": 1545.00,
      "title": "IPVA 2024 - Parcelado",
      "description": "IPVA 2024 parcelado em 3x",
      "type": "ipva",
      "year": 2024,
      "hasDiscount": false,
      "required": false,
      "dependsOn": [],
      "distinct": [
        "A1B2C3D4-1234-5678-90AB-CDEF12345678"
      ]
    }
  ]
}
```

No exemplo acima:

* **IPVA Cota Única** e **IPVA Parcelado** são mutuamente exclusivos
* O usuário deve escolher apenas uma das opções

### Como Validar

Valide se não há débitos distintos selecionados juntos:

<CodeGroup>
  ```javascript JavaScript theme={null}
  function validarDebitosDistintos(debitosSelecionados) {
    for (const debito of debitosSelecionados) {
      // Verifica se o débito tem restrições de distintos
      if (debito.distinct && debito.distinct.length > 0) {
        // Verifica se algum débito distinto foi selecionado
        for (const distintoId of debito.distinct) {
          const distintoIncluido = debitosSelecionados.some(
            d => d.id === distintoId
          );
          
          if (distintoIncluido) {
            const distintoDebito = debitosSelecionados.find(
              d => d.id === distintoId
            );
            throw new Error(
              `Os débitos "${debito.title}" e "${distintoDebito.title}" ` +
              `não podem ser pagos juntos. Escolha apenas um.`
            );
          }
        }
      }
    }
    
    return true;
  }

  // Exemplo de uso
  try {
    validarDebitosDistintos(debitosSelecionados);
    // Prosseguir com o pagamento
  } catch (error) {
    console.error(error.message);
    // Exibir mensagem ao usuário
  }
  ```

  ```python Python theme={null}
  def validar_debitos_distintos(debitos_selecionados):
      """
      Valida se não há débitos distintos selecionados juntos
      """
      for debito in debitos_selecionados:
          # Verifica se o débito tem restrições de distintos
          if debito.get('distinct') and len(debito['distinct']) > 0:
              # Verifica se algum débito distinto foi selecionado
              for distinto_id in debito['distinct']:
                  distinto_incluido = any(
                      d['id'] == distinto_id 
                      for d in debitos_selecionados
                  )
                  
                  if distinto_incluido:
                      distinto_debito = next(
                          d for d in debitos_selecionados 
                          if d['id'] == distinto_id
                      )
                      raise ValueError(
                          f"Os débitos '{debito['title']}' e "
                          f"'{distinto_debito['title']}' não podem ser pagos juntos. "
                          f"Escolha apenas um."
                      )
      
      return True

  # Exemplo de uso
  try:
      validar_debitos_distintos(debitos_selecionados)
      # Prosseguir com o pagamento
  except ValueError as error:
      print(error)
      # Exibir mensagem ao usuário
  ```
</CodeGroup>

### Erro ao Não Respeitar Distintos

Se você tentar pagar débitos distintos juntos, a API retornará um erro:

```json theme={null}
{
  "error": {
    "code": "DISTINCT_DEBTS_CONFLICT",
    "message": "Existem débitos que não podem ser pagos em conjunto",
    "details": {
      "conflictingDebts": [
        {
          "id": "A1B2C3D4-1234-5678-90AB-CDEF12345678",
          "title": "IPVA 2024 - Cota Única"
        },
        {
          "id": "E5F6G7H8-9012-3456-78IJ-KLMN90123456",
          "title": "IPVA 2024 - Parcelado"
        }
      ]
    }
  }
}
```

## Débitos Obrigatórios (required)

### O que são?

Débitos obrigatórios são aqueles que **sempre devem ser incluídos** no pagamento quando retornados na consulta. Não é possível pagar outros débitos sem incluir os obrigatórios.

### Exemplo Comum

O **Seguro Obrigatório (DPVAT)** é frequentemente marcado como obrigatório quando há outros débitos a serem pagos.

<Info>
  **Regra**: Se um débito obrigatório está presente na consulta e você está pagando outros débitos, o obrigatório também deve ser incluído.
</Info>

### Estrutura da Resposta

Cada débito possui um campo `required` (booleano) que indica se ele é obrigatório:

```json theme={null}
{
  "debts": [
    {
      "id": "87D4B252-1A3D-4918-A390-1C911424485B",
      "amount": 5.23,
      "title": "Seguro Obrigatório 2024",
      "description": "Seguro Obrigatório (DPVAT) 2024",
      "type": "insurance",
      "year": 2024,
      "required": true,
      "dependsOn": [],
      "distinct": []
    },
    {
      "id": "577FE0F7-2143-4236-BBC3-7AD071409298",
      "amount": 1864.04,
      "title": "Licenciamento 2024",
      "description": "Licenciamento 2024",
      "type": "licensing",
      "year": 2024,
      "required": false,
      "dependsOn": [],
      "distinct": []
    }
  ]
}
```

No exemplo acima:

* O **Seguro Obrigatório** tem `required: true`
* Se você for pagar o **Licenciamento**, deve incluir o **Seguro Obrigatório** também

### Como Validar

Valide se todos os débitos obrigatórios estão incluídos quando há outros débitos selecionados:

<CodeGroup>
  ```javascript JavaScript theme={null}
  function validarDebitosObrigatorios(debitosSelecionados, todosDebitos) {
    // Se não há débitos selecionados, não precisa validar
    if (debitosSelecionados.length === 0) {
      return true;
    }
    
    // Encontra todos os débitos obrigatórios
    const debitosObrigatorios = todosDebitos.filter(d => d.required === true);
    
    // Verifica se todos os obrigatórios estão selecionados
    for (const obrigatorio of debitosObrigatorios) {
      const obrigatorioIncluido = debitosSelecionados.some(
        d => d.id === obrigatorio.id
      );
      
      if (!obrigatorioIncluido) {
        throw new Error(
          `O débito "${obrigatorio.title}" é obrigatório e deve ser incluído ` +
          `no pagamento.`
        );
      }
    }
    
    return true;
  }

  // Exemplo de uso
  try {
    validarDebitosObrigatorios(debitosSelecionados, todosDebitos);
    // Prosseguir com o pagamento
  } catch (error) {
    console.error(error.message);
    // Exibir mensagem ao usuário
  }
  ```

  ```python Python theme={null}
  def validar_debitos_obrigatorios(debitos_selecionados, todos_debitos):
      """
      Valida se todos os débitos obrigatórios estão incluídos
      """
      # Se não há débitos selecionados, não precisa validar
      if len(debitos_selecionados) == 0:
          return True
      
      # Encontra todos os débitos obrigatórios
      debitos_obrigatorios = [
          d for d in todos_debitos 
          if d.get('required') == True
      ]
      
      # Verifica se todos os obrigatórios estão selecionados
      for obrigatorio in debitos_obrigatorios:
          obrigatorio_incluido = any(
              d['id'] == obrigatorio['id'] 
              for d in debitos_selecionados
          )
          
          if not obrigatorio_incluido:
              raise ValueError(
                  f"O débito '{obrigatorio['title']}' é obrigatório e "
                  f"deve ser incluído no pagamento."
              )
      
      return True

  # Exemplo de uso
  try:
      validar_debitos_obrigatorios(debitos_selecionados, todos_debitos)
      # Prosseguir com o pagamento
  except ValueError as error:
      print(error)
      # Exibir mensagem ao usuário
  ```
</CodeGroup>

### Erro ao Não Incluir Obrigatórios

Se você tentar pagar débitos sem incluir os obrigatórios, a API retornará um erro:

```json theme={null}
{
  "error": {
    "code": "REQUIRED_DEBTS_MISSING",
    "message": "Existem débitos obrigatórios que devem ser pagos",
    "details": {
      "requiredDebts": [
        {
          "id": "87D4B252-1A3D-4918-A390-1C911424485B",
          "title": "Seguro Obrigatório 2024"
        }
      ]
    }
  }
}
```

## Validação Completa

Para garantir que sua solicitação de pagamento seja processada corretamente, você deve validar todas as três regras:

<CodeGroup>
  ```javascript JavaScript theme={null}
  function validarSelecaoDebitos(debitosSelecionados, todosDebitos) {
    try {
      // 1. Valida débitos obrigatórios
      validarDebitosObrigatorios(debitosSelecionados, todosDebitos);
      
      // 2. Valida débitos dependentes
      validarDebitos(debitosSelecionados, todosDebitos);
      
      // 3. Valida débitos distintos
      validarDebitosDistintos(debitosSelecionados);
      
      return {
        valid: true,
        message: 'Seleção de débitos válida'
      };
    } catch (error) {
      return {
        valid: false,
        message: error.message
      };
    }
  }

  // Exemplo de uso
  const resultado = validarSelecaoDebitos(debitosSelecionados, todosDebitos);

  if (resultado.valid) {
    // Prosseguir com o pagamento
    processarPagamento(debitosSelecionados);
  } else {
    // Exibir mensagem de erro ao usuário
    alert(resultado.message);
  }
  ```

  ```python Python theme={null}
  def validar_selecao_debitos(debitos_selecionados, todos_debitos):
      """
      Valida todas as regras de seleção de débitos
      """
      try:
          # 1. Valida débitos obrigatórios
          validar_debitos_obrigatorios(debitos_selecionados, todos_debitos)
          
          # 2. Valida débitos dependentes
          validar_debitos(debitos_selecionados, todos_debitos)
          
          # 3. Valida débitos distintos
          validar_debitos_distintos(debitos_selecionados)
          
          return {
              'valid': True,
              'message': 'Seleção de débitos válida'
          }
      except ValueError as error:
          return {
              'valid': False,
              'message': str(error)
          }

  # Exemplo de uso
  resultado = validar_selecao_debitos(debitos_selecionados, todos_debitos)

  if resultado['valid']:
      # Prosseguir com o pagamento
      processar_pagamento(debitos_selecionados)
  else:
      # Exibir mensagem de erro ao usuário
      print(resultado['message'])
  ```
</CodeGroup>

## Experiência do Usuário

### Sugestões de Interface

Para uma melhor experiência do usuário, considere:

<AccordionGroup>
  <Accordion title="Seleção Automática de Dependências" icon="wand-magic-sparkles">
    Quando o usuário selecionar um débito que possui dependências, selecione automaticamente os débitos dependentes e desabilite a opção de desmarcá-los.

    ```javascript theme={null}
    function selecionarDebito(debitoId, todosDebitos) {
      const debito = todosDebitos.find(d => d.id === debitoId);
      const selecionados = [debito];
      
      // Adiciona dependências automaticamente
      if (debito.dependsOn && debito.dependsOn.length > 0) {
        debito.dependsOn.forEach(depId => {
          const dependencia = todosDebitos.find(d => d.id === depId);
          selecionados.push(dependencia);
        });
      }
      
      return selecionados;
    }
    ```
  </Accordion>

  <Accordion title="Desabilitar Opções Distintas" icon="ban">
    Quando o usuário selecionar um débito, desabilite automaticamente os débitos que são distintos dele.

    ```javascript theme={null}
    function desabilitarDistintos(debitoSelecionado, todosDebitos) {
      return todosDebitos.map(debito => ({
        ...debito,
        disabled: debitoSelecionado.distinct.includes(debito.id)
      }));
    }
    ```
  </Accordion>

  <Accordion title="Destacar Débitos Obrigatórios" icon="exclamation-triangle">
    Marque visualmente os débitos obrigatórios e não permita que sejam desmarcados.

    ```javascript theme={null}
    function renderizarDebito(debito) {
      return (
        <div className={debito.required ? 'debito-obrigatorio' : ''}>
          <input 
            type="checkbox" 
            checked={debito.selected}
            disabled={debito.required}
          />
          <span>{debito.title}</span>
          {debito.required && <span className="badge">Obrigatório</span>}
        </div>
      );
    }
    ```
  </Accordion>

  <Accordion title="Mensagens Explicativas" icon="circle-info">
    Exiba mensagens claras explicando por que certos débitos foram selecionados ou desabilitados.

    ```javascript theme={null}
    function getMensagemDebito(debito, todosDebitos) {
      if (debito.required) {
        return 'Este débito é obrigatório e deve ser pago';
      }
      
      if (debito.dependsOn && debito.dependsOn.length > 0) {
        const deps = debito.dependsOn.map(id => 
          todosDebitos.find(d => d.id === id).title
        ).join(', ');
        return `Depende de: ${deps}`;
      }
      
      if (debito.distinct && debito.distinct.length > 0) {
        return 'Não pode ser pago junto com outras opções de IPVA';
      }
      
      return '';
    }
    ```
  </Accordion>
</AccordionGroup>

## Testando com Placas de Homologação

Use as placas de teste específicas para validar o tratamento dessas regras:

<CardGroup cols={3}>
  <Card title="Débitos Dependentes" icon="link" href="/placas-teste#cenarios-de-dependencia-de-debitos">
    **DEP0001** a **DEP0007**

    Teste cenários com débitos que devem ser pagos juntos
  </Card>

  <Card title="Débitos Distintos" icon="ban" href="/placas-teste#cenarios-de-debitos-distintos">
    **DIS0001** a **DIS0003**

    Teste cenários com IPVA parcelado e cota única
  </Card>

  <Card title="Débitos Obrigatórios" icon="shield-check" href="/placas-teste#cenarios-de-debitos-obrigatorios">
    **REQ0001**

    Teste cenário com seguro obrigatório
  </Card>
</CardGroup>

## Resumo das Regras

<Steps>
  <Step title="Débitos Obrigatórios">
    Se houver débitos com `required: true`, eles **devem** ser incluídos no pagamento
  </Step>

  <Step title="Débitos Dependentes">
    Se um débito possui IDs no array `dependsOn`, **todos** esses débitos devem ser incluídos juntos
  </Step>

  <Step title="Débitos Distintos">
    Se um débito possui IDs no array `distinct`, **nenhum** desses débitos pode ser incluído junto
  </Step>

  <Step title="Validação Completa">
    Valide as três regras antes de enviar a solicitação de pagamento para evitar erros
  </Step>
</Steps>

## Referências

<CardGroup cols={2}>
  <Card title="Consulta de Débitos" icon="magnifying-glass-dollar" href="/consulta-debitos">
    Veja como consultar débitos e obter essas informações
  </Card>

  <Card title="Placas de Teste" icon="vial" href="/placas-teste">
    Use placas específicas para testar esses cenários
  </Card>

  <Card title="Fluxo Completo" icon="diagram-project" href="/fluxo-completo">
    Integração completa incluindo validação de débitos
  </Card>

  <Card title="Referência da API" icon="code" href="/api-reference/introduction">
    Documentação técnica completa da API
  </Card>
</CardGroup>
