# Preços

Tabela de preços do produto. Dois modelos: **único** (`default`) ou **progressivo por quantidade** (`wholesale`, até 5 faixas).

> Pré-requisitos: leia [Produtos: visão geral](/guia/produtos). O `price_type` é definido no próprio produto (`POST /api/products`); este guia trata só da tabela de preços por trás dele.

---

## Conceitos

**`price_type`** vive no produto e dita o comportamento da tabela:

| `price_type` | Faixas permitidas | `min_quantity` |
|---|---|---|
| `default` | Exatamente **1** | Sempre `1` |
| `wholesale` | **1 a 5** progressivas | `1`, depois valores crescentes |

**Faixa** é cada linha da tabela: par `(min_quantity, price)`. A faixa que vale numa venda é a de maior `min_quantity` cujo valor é `≤` quantidade comprada.

A chave de cada faixa é o `min_quantity`. É por isso que `PUT` e `DELETE` recebem ele no path.

> **Quer voltar de `wholesale` para `default`?** Só depois de deixar uma faixa só. Como o `default` é, por definição, uma tabela de uma linha, a plataforma não tem como adivinhar qual das suas faixas de atacado deve sobreviver — então a decisão fica com você: apague as faixas extras primeiro e aí a troca é liberada.

`GET /products/{id}/prices` devolve sempre um **array de faixas** — o que muda é o conteúdo conforme o `price_type`.

**Padrão (`default`)** — exatamente 1 faixa, sem medidas:

```jsonc
[
  {
    "min_quantity": 1,        // sempre 1 no default
    "value": 89.9,            // preço unitário único
    "discount_percent": null, // não se aplica
    "package_weight": null,   // medidas ficam null no default
    "package_height": null,
    "package_width": null,
    "package_length": null
  }
]
```

**Atacado (`wholesale`)** — 1 a 5 faixas progressivas, cada uma com as medidas da embalagem:

```jsonc
[
  {
    "min_quantity": 1,        // faixa base: preço e medidas de UMA unidade
    "value": 50.0,
    "discount_percent": null, // no atacado automático a base fica 0; o % vai nas faixas seguintes
    "package_weight": 1.2,
    "package_height": 10.0,
    "package_width": 12.0,
    "package_length": 15.0
  },
  {
    "min_quantity": 10,       // faixa de atacado: a partir de 10 un
    "value": 45.0,            //   preço unitário menor
    "discount_percent": null,
    "package_weight": 12.5,   // medidas da EMBALAGEM fechada
    "package_height": 30.0,
    "package_width": 40.0,
    "package_length": 50.0
  }
]
```

---

## Preço padrão (`default`)

Produto vendido por valor unitário. Uma única faixa, sempre com `min_quantity = 1`.

### Criar

<a class="api-route" href="/reference/produtos#tag/preços-de-produtos/POST/api/products/{id}/prices"><span class="api-method api-method-post">POST</span><span class="api-path">/api/products/{id}/prices</span></a>

```json
{
  "min_quantity": 1,
  "price": 89.90
}
```

### Atualizar

<a class="api-route" href="/reference/produtos#tag/preços-de-produtos/PUT/api/products/{id}/prices/{min_quantity}"><span class="api-method api-method-put">PUT</span><span class="api-path">/api/products/{id}/prices/1</span></a>

```json
{
  "price": 79.90
}
```

---

## Preço de atacado (`wholesale`)

Tabela progressiva por volume, até 5 faixas. Cada faixa tem o **preço unitário** vendido **a partir** daquela quantidade.

> **Recomendado: precifique por desconto (`%`), não por valor fixo.** Ligando o `auto_wholesale_pricing`, você informa só o `discount_percent` de cada faixa e deixa o preço ser derivado do preço base. A gestão fica **automática**: você reajusta o preço base num lugar só e **todas as faixas se recalculam sozinhas** — sem reabrir faixa por faixa e sem risco de a tabela ficar inconsistente. Os dois modos estão documentados abaixo, mas comece pelo [Atacado automático](#atacado-automatico).

Exemplo de tabela montada:

| Faixa | `min_quantity` | `price` (unitário) | Quando vale |
|---|---|---|---|
| 1 | 1 | R$ 50,00 | 1 a 9 unidades |
| 2 | 10 | R$ 45,00 | 10 a 49 unidades |
| 3 | 50 | R$ 40,00 | 50 unidades ou mais |

A faixa base (`min_quantity = 1`) é sempre o preço unitário. As faixas de atacado são as de `min_quantity ≥ 2`.

### Medidas da embalagem (obrigatórias)

Toda faixa de atacado representa uma **embalagem fechada** (caixa/fardo) — é com ela que a plataforma calcula o frete da venda fracionada. Por isso, a **primeira faixa de atacado precisa trazer as medidas completas** da embalagem:

| Campo | Unidade | Regra |
|---|---|---|
| `package_weight` | kg | > 0 |
| `package_height` | cm | > 0 |
| `package_width` | cm | > 0 |
| `package_length` | cm | > 0 |

Os quatro campos são **tudo-ou-nada**: ou você manda os quatro, ou nenhum. Mandar só parte deles é recusado com `422`.

Depois que existe **uma** faixa medida, as faixas seguintes podem ser criadas **sem** as medidas — elas herdam a embalagem de referência. O produto só não pode ficar sem nenhuma faixa medida: por isso a remoção da última faixa com medidas (havendo outras faixas dependendo dela) também é recusada com `422`.

> A faixa base (`min_quantity = 1`) carrega as medidas de **uma unidade** (o produto avulso); as faixas de atacado (`min_quantity ≥ 2`) carregam as medidas da **embalagem fechada** vendida naquela faixa. Assim o frete sai correto tanto na venda unitária quanto no fardo.

### Adicionar uma faixa (modo manual)

<a class="api-route" href="/reference/produtos#tag/preços-de-produtos/POST/api/products/{id}/prices"><span class="api-method api-method-post">POST</span><span class="api-path">/api/products/{id}/prices</span></a>

No modo manual você informa o `price` de cada faixa diretamente — e fica responsável por reajustar faixa a faixa quando o preço mudar. (Para uma gestão mais simples, prefira o [Atacado automático](#atacado-automatico) — a abordagem recomendada — em que você precifica por desconto.)

Faixa base (`min_quantity = 1`) — só o preço. As medidas de **uma unidade** vivem no cadastro do produto (`dimensions`, ver [Produtos: visão geral](/guia/produtos)) e são apenas projetadas na leitura da faixa base — enviar `package_*` aqui não tem efeito:

```json
{
  "min_quantity": 1,
  "price": 50.00
}
```

Primeira faixa de atacado — com as medidas da **embalagem fechada**:

```json
{
  "min_quantity": 10,
  "price": 45.00,
  "package_weight": 12.5,
  "package_height": 30.0,
  "package_width": 40.0,
  "package_length": 50.0
}
```

Faixas seguintes podem omitir as medidas (herdam a referência):

```json
{
  "min_quantity": 50,
  "price": 40.00
}
```

### Reajustar uma faixa existente

<a class="api-route" href="/reference/produtos#tag/preços-de-produtos/PUT/api/products/{id}/prices/{min_quantity}"><span class="api-method api-method-put">PUT</span><span class="api-path">/api/products/{id}/prices/10</span></a>

O corpo aceita o `price` e/ou as medidas. O merge parcial vale só para as medidas e o `discount_percent` — **o `price` não**: se você não mandar, ele é zerado (no modo manual e na faixa base). Sempre reenvie o `price` no `PUT`.

```json
{
  "price": 42.50
}
```

### Remover uma faixa

<a class="api-route" href="/reference/produtos#tag/preços-de-produtos/DELETE/api/products/{id}/prices/{min_quantity}"><span class="api-method api-method-delete">DELETE</span><span class="api-path">/api/products/{id}/prices/10</span></a>

---

## Atacado automático

**É a abordagem recomendada para o atacado:** o preço passa a ser gerido num ponto só, o que mantém a tabela sempre coerente.

O produto tem um interruptor `auto_wholesale_pricing` (definido no próprio produto, junto do `price_type`). Quando **ligado**, você para de informar o `price` das faixas de atacado e passa a informar só o **desconto** (`discount_percent`) — o preço de cada faixa é **derivado do preço unitário base menos o desconto**.

O `discount_percent` é sempre **relativo ao preço base**. O que fica salvo na faixa é o desconto, não um valor fixo: por isso, **se você mudar o preço base, todas as faixas de atacado são recalculadas** aplicando de novo o desconto de cada uma. Você ajusta o preço num lugar só.

Exemplo: preço base R$ 50,00, faixa de 50 un com `discount_percent: 20` → preço da faixa = R$ 40,00. Se depois o base virar R$ 60,00, a mesma faixa passa sozinha para R$ 48,00.

Regras desse modo:

- O **preço base** (`min_quantity = 1`) precisa existir antes de criar faixas de atacado — é dele que sai o cálculo. Sem ele, a API responde `422`.
- O `discount_percent` vai de `0` a menos de `100`.
- Os descontos precisam ser **progressivos**: faixa de quantidade maior exige desconto maior que a anterior (o preço sempre cai conforme a quantidade sobe). Caso contrário, `422`.

Faixa de atacado por desconto (em vez de `price`):

```json
{
  "min_quantity": 50,
  "discount_percent": 20,
  "package_weight": 12.5,
  "package_height": 30.0,
  "package_width": 40.0,
  "package_length": 50.0
}
```

> Comparando os dois modos para a mesma faixa: no **manual** você manda `"price": 40.00`; no **automático** você manda `"discount_percent": 20` e a API calcula o preço a partir do base. No modo manual o `discount_percent` é ignorado.

---

## Listar a tabela

<a class="api-route" href="/reference/produtos#tag/preços-de-produtos/GET/api/products/{id}/prices"><span class="api-method api-method-get">GET</span><span class="api-path">/api/products/{id}/prices</span></a>

```json
{
  "success": true,
  "message_code": "SUCCESS",
  "data": [
    {
      "value": 50.00,
      "min_quantity": 1,
      "discount_percent": null,
      "package_weight": 1.2,
      "package_height": 10.0,
      "package_width": 12.0,
      "package_length": 15.0
    },
    {
      "value": 45.00,
      "min_quantity": 10,
      "discount_percent": null,
      "package_weight": 12.5,
      "package_height": 30.0,
      "package_width": 40.0,
      "package_length": 50.0
    }
  ]
}
```

Cada faixa traz o valor (`value`), o `min_quantity`, o `discount_percent` (preenchido no atacado automático) e as medidas da embalagem. Já vem ordenado por `min_quantity` ascendente, pronto pra renderizar na tela do comprador.
