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

# Promotional

> Promoção de uma Company para catálogo, descoberta e validação no checkout

O `Promotional` representa uma promoção configurada por uma [Company](/data-modelling/tenant/company). Ele centraliza os dados comuns de catálogo, desconto, período de validade e status. A validação específica fica em uma tabela de regra fixa, conforme o `type`.

## Campos

| Campo                | Tipo                      | Descrição                                                              |
| -------------------- | ------------------------- | ---------------------------------------------------------------------- |
| `promotionalId`      | `UUID`                    | Identificador único                                                    |
| `organizationId`     | `UUID`                    | Organização da Company responsável pela promoção                       |
| `companyId`          | `UUID`                    | Company dona da promoção                                               |
| `code`               | `String`                  | Código legível único da promoção                                       |
| `name`               | `String`                  | Nome interno da promoção                                               |
| `description`        | `String?`                 | Descrição interna da campanha                                          |
| `displayTitle`       | `String`                  | Título exibido para o cliente no catálogo                              |
| `displayDescription` | `String?`                 | Texto curto exibido para o cliente antes do checkout                   |
| `callToActionLabel`  | `String?`                 | Texto do CTA exibido no front                                          |
| `type`               | `PromotionalType`         | Tipo fixo da promoção                                                  |
| `discountType`       | `PromotionalDiscountType` | Forma de cálculo do desconto                                           |
| `discountValue`      | `Int`                     | Valor do desconto em centavos ou basis points, conforme `discountType` |
| `maxDiscountAmount`  | `Int?`                    | Teto de desconto em centavos, quando aplicável                         |
| `allowedChannels`    | `String[]`                | Canais onde a promoção pode aparecer ou ser aplicada                   |
| `stackable`          | `Boolean`                 | Indica se pode combinar com outros descontos                           |
| `priority`           | `Int`                     | Prioridade de exibição e desempate                                     |
| `startsAt`           | `DateTime?`               | Início da validade da promoção                                         |
| `endsAt`             | `DateTime?`               | Fim da validade da promoção                                            |
| `status`             | `PromotionalStatus`       | Status da promoção                                                     |
| `createdBy`          | `UUID?`                   | Usuário que criou o registro, quando aplicável                         |
| `createdAt`          | `DateTime`                | Data de criação                                                        |
| `updatedBy`          | `UUID?`                   | Usuário que fez a última atualização, quando aplicável                 |
| `updatedAt`          | `DateTime`                | Data da última atualização                                             |
| `deletedBy`          | `UUID?`                   | Usuário que removeu o registro, quando aplicável                       |
| `deletedAt`          | `DateTime?`               | Data de remoção lógica                                                 |

## Relacionamentos

* Relaciona-se com [Organization](/data-modelling/tenant/organization) por `organizationId`.
* Relaciona-se com [Company](/data-modelling/tenant/company) por `companyId`.
* Relaciona-se com [PromotionalRouteRule](/data-modelling/promotion/promotional-route-rule), quando `type = ROUTE`.
* Relaciona-se com [PromotionalRoundTripRule](/data-modelling/promotion/promotional-round-trip-rule), quando `type = ROUND_TRIP`.
* Relaciona-se com [PromotionalMultiTicketRule](/data-modelling/promotion/promotional-multi-ticket-rule), quando `type = MULTI_TICKET`.
* Relaciona-se com [PromotionalLowDemandTimeRule](/data-modelling/promotion/promotional-low-demand-time-rule), quando `type = LOW_DEMAND_TIME`.
* Relaciona-se com múltiplos [PromotionalUsageHistory](/data-modelling/promotion/promotional-usage-history).

## Regras de Negócio

* A promoção pertence à Company indicada em `companyId` e só pode ser aplicada em compras da mesma Company.
* `type` define qual tabela de regra deve existir para validar a promoção.
* Cada promoção deve ter exatamente uma regra ativa compatível com o `type`.
* Uma promoção `ROUTE` deve ter uma [PromotionalRouteRule](/data-modelling/promotion/promotional-route-rule).
* Uma promoção `ROUND_TRIP` deve ter uma [PromotionalRoundTripRule](/data-modelling/promotion/promotional-round-trip-rule).
* Uma promoção `MULTI_TICKET` deve ter uma [PromotionalMultiTicketRule](/data-modelling/promotion/promotional-multi-ticket-rule).
* Uma promoção `LOW_DEMAND_TIME` deve ter uma [PromotionalLowDemandTimeRule](/data-modelling/promotion/promotional-low-demand-time-rule).
* O front pode exibir a promoção usando os campos de catálogo e a regra fixa correspondente, antes de o carrinho estar completo.
* Exibir uma promoção no catálogo não garante aplicação; a aplicação depende da validação final no checkout.
* `discountValue` usa centavos quando `discountType = FIXED_AMOUNT` e basis points quando `discountType = PERCENTAGE`.
* `maxDiscountAmount` limita o desconto percentual quando preenchido.
* `allowedChannels` controla se a promoção aparece em canais como app, web, agência ou venda assistida.
* `priority` ordena a exibição e resolve conflitos quando múltiplas promoções elegíveis disputam o mesmo contexto.
* Se `stackable = false`, a promoção não pode ser combinada com outro desconto aplicado ao mesmo item de compra.
* Promoções ativas devem respeitar `startsAt`, `endsAt`, `status`, Company, canal e a regra fixa correspondente.
* Cada aplicação confirmada deve gerar um [PromotionalUsageHistory](/data-modelling/promotion/promotional-usage-history).
* `createdBy`, `updatedBy` e `deletedBy` seguem o padrão de auditoria do DEVMOB e registram o usuário responsável pela mutação, quando aplicável.

## Enums

### PromotionalType

| Valor             | Descrição                                |
| ----------------- | ---------------------------------------- |
| `ROUND_TRIP`      | Incentivo para compra de ida e volta     |
| `MULTI_TICKET`    | Desconto por quantidade de passagens     |
| `ROUTE`           | Promoção específica por rota             |
| `LOW_DEMAND_TIME` | Incentivo para horários de menor demanda |

### PromotionalDiscountType

| Valor          | Descrição                           |
| -------------- | ----------------------------------- |
| `PERCENTAGE`   | Desconto percentual em basis points |
| `FIXED_AMOUNT` | Desconto fixo em centavos           |

### PromotionalStatus

| Valor      | Descrição                       |
| ---------- | ------------------------------- |
| `DRAFT`    | Promoção em rascunho            |
| `ACTIVE`   | Promoção ativa                  |
| `INACTIVE` | Promoção inativa manualmente    |
| `EXPIRED`  | Promoção encerrada por validade |

## Example

```json theme={null}
{
  "promotionalId": "0197f7c0-55de-7b18-9073-c7d7c8c9a441",
  "organizationId": "0197a801-1690-7590-b3cf-19599b9be3e4",
  "companyId": "0197a801-6a42-79aa-9e56-d3c85148c0fa",
  "code": "PROMO-ROTA-10",
  "name": "Rota com 10%",
  "description": "Campanha para rota específica.",
  "displayTitle": "Economize nesta rota",
  "displayDescription": "Receba desconto ao viajar pela rota selecionada.",
  "callToActionLabel": "Ver horários",
  "type": "ROUTE",
  "discountType": "PERCENTAGE",
  "discountValue": 1000,
  "maxDiscountAmount": 3000,
  "allowedChannels": ["WEB", "APP"],
  "stackable": false,
  "priority": 10,
  "startsAt": "2026-07-04T00:00:00.000Z",
  "endsAt": "2026-08-31T23:59:59.000Z",
  "status": "ACTIVE",
  "createdBy": "0197a805-0910-7eb2-bae7-90a13df2a9b2",
  "createdAt": "2026-07-04T15:00:00.000Z",
  "updatedBy": "0197a805-0910-7eb2-bae7-90a13df2a9b2",
  "updatedAt": "2026-07-04T15:00:00.000Z",
  "deletedBy": null,
  "deletedAt": null
}
```
