# Integração PDV Avanço — Consulta de Descontos e Envio de Venda (Parceiros CRM)

> **Objetivo**  
> Documentar o fluxo PDV → Parceiro de Fidelidade/Descontos (ex.: "crescevendas" como placeholder), com exemplos de requisição e retorno, e a explicação dos campos utilizados. O documento é **genérico** e pode ser aplicado a qualquer parceiro que exponha endpoints equivalentes.

---

## Visão geral do fluxo

1. **Consulta de descontos** (pré-venda): o PDV envia os itens do carrinho + identificação do cliente → **API do parceiro** retorna descontos aplicáveis e dados do cliente.
2. **Envio da venda** (pós-fechamento): o PDV registra a venda efetuada (itens, pagamento, total) → **API do parceiro** confirma pontos/saldo/benefícios concedidos e retorna os saldos finais.

> **Observação:** os nomes de host, caminhos e cabeçalhos abaixo são **exemplos**. Adapte-os ao parceiro real (ex.: `https://{host-parceiro}/admin/api/v2/...`).

---

## Padrões comuns

- **Formato**: JSON (UTF-8).
- **Métodos**: `POST` para as operações descritas.
- **Timeout recomendado no PDV**: 30s.
- **Autenticação**: via cabeçalhos proprietários do parceiro (ex.: `X-AdminUser-Email`, `X-AdminUser-Token`).
- **Idioma**: quando suportado, enviar `Accept-Language: pt-BR`.

### Cabeçalhos (exemplo)

```
Accept: */*
Content-Type: application/json
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
charsets: utf-8
X-AdminUser-Email: <email-de-integracao@parceiro>
X-AdminUser-Token: <token-de-integracao>

```

---

## 1) Consulta de Descontos (pré-venda)

**Endpoint (exemplo):**

```
POST https://{host-parceiro}/admin/api/v2/shops

```

### Request — Exemplo de `curl`

```bash
curl -k -m 30 -s -S \
  -H "Accept: */*" \
  -H "Content-Type: application/json" \
  -H "Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4" \
  -H "charsets: utf-8" \
  -H "X-AdminUser-Email: <email-de-integracao@parceiro>" \
  -H "X-AdminUser-Token: <token-de-integracao>" \
  -X POST \
  --data-binary @inicia_parceiro.json \
  "https://{host-parceiro}/admin/api/v2/shops" \
  -o retorno_consulta.json --stderr erro_consulta.log -D header_consulta.txt

```

### Request — Corpo (exemplo)

```json
{
  "items": [
    {
      "category": "046",
      "code": "00000000000017",
      "product_name": "CREME AMEND ALMOND B",
      "quantity": 1.0,
      "subcategory": "241",
      "unit_type": "um",
      "unit_value": 6.99
    }
  ],
  "registration": "05940778690"
}

```

### Significado dos campos (request)

<table id="bkmrk-campo-tipo-obrigat%C3%B3r"><thead><tr><th>Campo</th><th align="right">Tipo</th><th align="center">Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td>`items`</td><td align="right">Array de objeto</td><td align="center">Sim</td><td>Lista de itens no carrinho do PDV para avaliação de desconto.</td></tr><tr><td>`items[].category`</td><td align="right">string</td><td align="center">Recomendado</td><td>Código de **categoria mercadológica** do item no PDV.</td></tr><tr><td>`items[].subcategory`</td><td align="right">string</td><td align="center">Opcional</td><td>Código de **subcategoria** mercadológica.</td></tr><tr><td>`items[].code`</td><td align="right">string</td><td align="center">Sim</td><td>Identificador do produto (EAN/PLU/código interno).</td></tr><tr><td>`items[].product_name`</td><td align="right">string</td><td align="center">Recomendado</td><td>Descrição do produto.</td></tr><tr><td>`items[].quantity`</td><td align="right">number</td><td align="center">Sim</td><td>Quantidade do item.</td></tr><tr><td>`items[].unit_type`</td><td align="right">string</td><td align="center">Recomendado</td><td>Unidade de medida (ex.: `um`, `kg`, `lt`).</td></tr><tr><td>`items[].unit_value`</td><td align="right">number</td><td align="center">Sim</td><td>Preço unitário vigente no PDV (antes de desconto).</td></tr><tr><td>`registration`</td><td align="right">string</td><td align="center">Sim</td><td>Identificação do cliente para o parceiro. **Ex.: CPF** (somente números).</td></tr></tbody></table>

> **Boas práticas:**
> 
> - Enviar `unit_value` já no **valor de venda** do PDV; o parceiro retornará descontos/propostas.
> - Se houver mix de unidades (ex.: peso/quilagem), alinhar previamente com o parceiro como enviar e arredondar.

### Response — Exemplo

```json
{
  "response": {
    "code": 200,
    "discounts": {
      "products": [],
      "subtotal": 0.0
    },
    "shop_id": "0909092413",
    "user": {
      "address": {
        "adjunct": "",
        "city": "Belo Horizonte",
        "district": "Santa Efigênia",
        "number": 131,
        "phone": "(31) 33333-3333",
        "state": "Minas Gerais",
        "street": "Avenida Brasil",
        "zipcode": "30140-000"
      },
      "name": "Heberth Minelli",
      "st_token": "11177821-d40a-40f8-9b58-9f50978682a9",
      "total_balance": 100.0,
      "total_points": 1969
    }
  }
}

```

### Significado dos campos (response)

<table id="bkmrk-campo-tipo-descri%C3%A7%C3%A3o"><thead><tr><th>Campo</th><th align="right">Tipo</th><th>Descrição</th></tr></thead><tbody><tr><td>`response.code`</td><td align="right">number</td><td>Código de status interno do parceiro (200 = sucesso). Não substitui o HTTP status.</td></tr><tr><td>`response.discounts.products`</td><td align="right">array</td><td>Detalhes de descontos por produto (quando aplicável).</td></tr><tr><td>`response.discounts.subtotal`</td><td align="right">number</td><td>Desconto total a ser aplicado no **subtotal** do carrinho (se houver).</td></tr><tr><td>`response.shop_id`</td><td align="right">string</td><td>Identificador da loja/estabelecimento no parceiro.</td></tr><tr><td>`response.user`</td><td align="right">objeto</td><td>Dados do cliente no ecossistema do parceiro (endereços, saldos, pontos).</td></tr><tr><td>`response.user.st_token`</td><td align="right">string</td><td>Token de sessão/identificação do cliente no parceiro (usar conforme política do parceiro).</td></tr><tr><td>`response.user.total_balance`</td><td align="right">number</td><td>Saldo monetário de benefícios (se aplicável).</td></tr><tr><td>`response.user.total_points`</td><td align="right">number</td><td>Pontos acumulados (se aplicável).</td></tr></tbody></table>

> **Aplicação no PDV:** o PDV pode aplicar descontos retornados (por item e/ou subtotal) e exibir dados do cliente (nome, pontos, etc.), conforme regras da loja.

---

## 2) Envio da Venda (pós-fechamento)

**Endpoint (exemplo):**

```
POST https://{host-parceiro}/admin/api/v2/sales

```

> O caminho acima é **exemplo**. Alguns parceiros usam `/shops/sales`, `/orders`, etc. Alinhe o endpoint definitivo na homologação.

### Request — Corpo (exemplo)

```json
{
  "discounts": [],
  "items": [
    {
      "category": "046",
      "code": "00000000000017",
      "product_name": "CREME AMEND ALMOND B",
      "quantity": 1.0,
      "subcategory": "241",
      "total_value": 6.99,
      "unit_type": "um",
      "unit_value": 6.99
    },
    {
      "category": "048",
      "code": "00000000000031",
      "product_name": "LEITE UHT PIRACANJUB",
      "quantity": 1.0,
      "subcategory": "269",
      "total_value": 1.0,
      "unit_type": "um",
      "unit_value": 1.0
    }
  ],
  "payment": {
    "coupon": "02290621.99",
    "date": "2025-09-09T11:12:20",
    "paymethod": [
      { "paymethod": 1, "value": 7.99 }
    ],
    "total": 7.99
  },
  "registration": "05940778690"
}

```

### Significado dos campos (request)

<table id="bkmrk-campo-tipo-obrigat%C3%B3r-1"><thead><tr><th>Campo</th><th align="right">Tipo</th><th align="center">Obrigatório</th><th>Descrição</th></tr></thead><tbody><tr><td>`discounts`</td><td align="right">array</td><td align="center">Opcional</td><td>Lista de descontos efetivamente aplicados na venda (quando o parceiro exige detalhar).</td></tr><tr><td>`items`</td><td align="right">array</td><td align="center">Sim</td><td>Itens efetivamente vendidos. Campos seguem a semântica da consulta, com **adição** de `total_value`.</td></tr><tr><td>`items[].total_value`</td><td align="right">number</td><td align="center">Sim</td><td>Valor total do item (já considerando quantidade e descontos).</td></tr><tr><td>`payment`</td><td align="right">objeto</td><td align="center">Sim</td><td>Dados do pagamento da venda.</td></tr><tr><td>`payment.coupon`</td><td align="right">string</td><td align="center">Recomendado</td><td>Identificador do cupom/ECF/NSU no PDV (para auditoria).</td></tr><tr><td>`payment.date`</td><td align="right">string (ISO-8601)</td><td align="center">Sim</td><td>Data/hora de fechamento da venda no PDV (ex.: `YYYY-MM-DDThh:mm:ss`).</td></tr><tr><td>`payment.paymethod[]`</td><td align="right">array</td><td align="center">Sim</td><td>Parcelas/meios de pagamento utilizados.</td></tr><tr><td>`payment.paymethod[].paymethod`</td><td align="right">number/string</td><td align="center">Sim</td><td>Código do meio de pagamento (tabela acordada com o parceiro).</td></tr><tr><td>`payment.paymethod[].value`</td><td align="right">number</td><td align="center">Sim</td><td>Valor pago com o respectivo meio.</td></tr><tr><td>`payment.total`</td><td align="right">number</td><td align="center">Sim</td><td>Total da venda (soma dos pagamentos).</td></tr><tr><td>`registration`</td><td align="right">string</td><td align="center">Sim</td><td>Identificação do cliente no parceiro (ex.: CPF).</td></tr></tbody></table>

> **Conciliação:** `payment.total` deve bater com a soma de `paymethod[].value`. Para múltiplos meios, adicione entradas no array.

### Response — Exemplo

```json
{
  "response": {
    "balance": 0.0,
    "code": 200,
    "future_balance": 0.0,
    "points": 8,
    "user": {
      "address": {
        "adjunct": "",
        "city": "Belo Horizonte",
        "district": "Santa Efigênia",
        "number": 131,
        "phone": "(31) 33333-3333",
        "state": "Minas Gerais",
        "street": "Avenida Brasil",
        "zipcode": "30140-000"
      },
      "name": "Heberth Minelli",
      "st_token": "11177821-d40a-40f8-9b58-9f50978682a9",
      "total_balance": 100.0,
      "total_points": 1977
    }
  }
}

```

### Significado dos campos (response)

<table id="bkmrk-campo-tipo-descri%C3%A7%C3%A3o-1"><thead><tr><th>Campo</th><th align="right">Tipo</th><th>Descrição</th></tr></thead><tbody><tr><td>`response.code`</td><td align="right">number</td><td>Código de processamento no parceiro (200 = sucesso).</td></tr><tr><td>`response.points`</td><td align="right">number</td><td>Pontos concedidos na venda.</td></tr><tr><td>`response.balance`</td><td align="right">number</td><td>Saldo monetário utilizado/remanescente após a venda (quando aplicável).</td></tr><tr><td>`response.future_balance`</td><td align="right">number</td><td>Saldo futuro (benefícios liberados em D+N, quando houver).</td></tr><tr><td>`response.user.total_points`</td><td align="right">number</td><td>Pontos totais do cliente **após** a venda.</td></tr><tr><td>`response.user.total_balance`</td><td align="right">number</td><td>Saldo total do cliente **após** a venda (quando aplicável).</td></tr></tbody></table>

---

## Considerações de implementação (PDV)

- **Idempotência:**
    
    
    - Recomenda-se enviar um **identificador único** por venda (ex.: `payment.coupon` + data) e, se o parceiro suportar, um cabeçalho `Idempotency-Key` para evitar lançamentos duplicados em reenvios.
- **Tratamento de erros:**
    
    
    - Mapear HTTP status (ex.: `4xx/5xx`) e também `response.code` do corpo quando houver. Implementar retentativas **somente** para erros transitórios.
- **Encoding:**
    
    
    - Garantir UTF-8 para nomes de produtos e logradouros; caso o parceiro retorne acentos com encoding incorreto, normalizar para exibição no PDV.
- **Tabelas de referência:**
    
    
    - `paymethod` (meios de pagamento) e eventuais códigos de categoria/subcategoria devem ser alinhados e versionados entre PDV e parceiro.
- **Segurança:**
    
    
    - Armazenar `X-AdminUser-Token` em cofre seguro. Nunca registrar token em logs de nível INFO/DEBUG.
- **Observabilidade:**
    
    
    - Logar request-id, latência, tamanho de payload e resumo do resultado (sem PII sensível) para facilitar diagnósticos.

---

## Anexos — Arquivos de exemplo

### `inicia_parceiro.json`

```json
{
  "items": [
    {
      "category": "046",
      "code": "00000000000017",
      "product_name": "CREME AMEND ALMOND B",
      "quantity": 1.0,
      "subcategory": "241",
      "unit_type": "um",
      "unit_value": 6.99
    }
  ],
  "registration": "05940778690"
}

```

### `retorno_consulta.json` (amostra)

```json
{
  "response": {
    "code": 200,
    "discounts": { "products": [], "subtotal": 0.0 },
    "shop_id": "0909092413",
    "user": {
      "name": "Heberth Minelli",
      "st_token": "11177821-d40a-40f8-9b58-9f50978682a9",
      "total_balance": 100.0,
      "total_points": 1969
    }
  }
}

```

### `venda_enviada.json`

```json
{
  "discounts": [],
  "items": [
    {
      "category": "046",
      "code": "00000000000017",
      "product_name": "CREME AMEND ALMOND B",
      "quantity": 1.0,
      "subcategory": "241",
      "total_value": 6.99,
      "unit_type": "um",
      "unit_value": 6.99
    },
    {
      "category": "048",
      "code": "00000000000031",
      "product_name": "LEITE UHT PIRACANJUB",
      "quantity": 1.0,
      "subcategory": "269",
      "total_value": 1.0,
      "unit_type": "um",
      "unit_value": 1.0
    }
  ],
  "payment": {
    "coupon": "02290621.99",
    "date": "2025-09-09T11:12:20",
    "paymethod": [ { "paymethod": 1, "value": 7.99 } ],
    "total": 7.99
  },
  "registration": "05940778690"
}

```

### `retorno_venda.json` (amostra)

```json
{
  "response": {
    "balance": 0.0,
    "code": 200,
    "future_balance": 0.0,
    "points": 8,
    "user": {
      "name": "Heberth Minelli",
      "st_token": "11177821-d40a-40f8-9b58-9f50978682a9",
      "total_balance": 100.0,
      "total_points": 1977
    }
  }
}

```

---

## Checklist de Homologação

- [ ]  [ ]  Confirmar **endpoints definitivos** (consulta e venda) e autenticação.
- [ ]  [ ]  Validar **mapeamento de `paymethod`** (códigos e formas aceitas).
- [ ]  [ ]  Verificar regras de **arredondamento** e casas decimais em itens/descontos.
- [ ]  [ ]  Ensaiar cenários com **múltiplos meios de pagamento** e cancelamento/estorno (se aplicável).
- [ ]  [ ]  Testar comportamento **offline/timeout** e diretrizes de reenvio (com idempotência).

---

> **Observação:** os exemplos de dados (CPF, nomes, tokens, códigos) são **fictícios** e servem apenas para demonstração. Substitua por valores reais na sua integração.