Fidelidade — Programa de Selos
O módulo fidelidade (backend/src/loyalty/) implementa programas de cartão-fidelidade do tipo stamp card (ex: "compre 9, ganhe 1 grátis"), vinculados a categorias do cardápio.
Visão Geral
| Característica | Detalhe |
|---|---|
| Módulo backend | backend/src/loyalty/ |
| Controller | loyalty.controller.ts |
| Schemas | LoyaltyCampaign, StampCard, RewardCode |
| Permissão admin | Admin ou Superadmin |
| Rota | /t/:slug/admin/loyalty |
Schemas
LoyaltyCampaign (schemas/campaign.schema.ts)
| Campo | Tipo | Descrição |
|---|---|---|
tenant | ObjectId | |
name | string | Nome interno da campanha |
qualifyingCategories | ObjectId[] | Categorias do cardápio que geram selos |
stampsRequired | number | Selos para completar o cartão |
rewardType | enum | free_item | percent_discount | fixed_discount |
rewardValue | number? | Percentual ou valor fixo (para os tipos de desconto) |
rewardItemId | ObjectId? | Item gratuito (quando rewardType = free_item) |
expirationDays | number? | Dias até cartão incompleto expirar |
active | boolean | |
totalStampsIssued | number | Contador acumulado |
totalCardsCompleted | number | |
totalRewardsRedeemed | number |
StampCard (schemas/stamp-card.schema.ts)
| Campo | Tipo | Descrição |
|---|---|---|
campaign | ObjectId → LoyaltyCampaign | |
tenant | ObjectId | |
customerPhone | string | Chave do cliente |
stamps | number | Selos acumulados neste cartão |
lastStampAt | Date | |
completedAt | Date? | null = cartão em aberto |
Índice único: { campaign, customerPhone, completedAt: null } — garante um cartão ativo por campanha por cliente.
RewardCode (schemas/reward-code.schema.ts)
Código gerado ao completar o cartão; único por campanha + cliente + data.
Fluxo de Stamp
Pedido pago → itens da categoria qualificante?
↓ Sim
LoyaltyService.stampCard(tenantId, customerPhone, orderId)
↓
StampCard.stamps += 1
↓ stamps >= stampsRequired?
↓ Sim
completedAt = now
RewardCode gerado (código hex aleatório)
Cliente recebe notificação WhatsApp com o códigoTipos de Prêmio
rewardType | Comportamento |
|---|---|
free_item | Adiciona o rewardItemId à próxima comanda sem custo |
percent_discount | Desconto percentual (ex: 20%) na próxima visita |
fixed_discount | Valor fixo em R$ de desconto |
Endpoints Admin
| Método | Rota | Descrição |
|---|---|---|
GET | /admin/loyalty/campaigns | Lista campanhas |
POST | /admin/loyalty/campaigns | Cria campanha |
PUT | /admin/loyalty/campaigns/:id | Atualiza campanha |
DELETE | /admin/loyalty/campaigns/:id | Exclui (soft) campanha |
GET | /admin/loyalty/campaigns/:id/stats | Stats da campanha |
GET | /admin/loyalty/cards/:customerPhone | Cartões de um cliente |
Endpoints Públicos (Cliente)
| Método | Rota | Descrição |
|---|---|---|
GET | /loyalty/campaigns | Campanhas ativas |
GET | /loyalty/cards/:phone | Cartões ativos do cliente |
POST | /loyalty/redeem | Resgatar código de prêmio |