PDV — Terminais de Venda
Visão Geral
Um PDV (Ponto de Venda) é o terminal onde as transações ocorrem. Cada PDV pertence a uma Filial (Branch) — a relação é N:1. Uma filial pode operar 10+ terminais simultâneos.
Branch (1) ──── PDV (N) ──── Shift (N) ──── Order (N)Localização
frontend-react/src/views/admin/PdvManagementView.tsxbackend/src/pdvs/schemas/pdv.schema.ts
Rota
/t/:slug/admin/pdv
Schema
| Campo | Tipo | Descrição |
|---|---|---|
tenant | ObjectId | Tenant |
branch | ObjectId? | Filial pai — FK para Branch (adicionado na feature enterprise) |
name | string | Nome do terminal (ex: "Caixa 1") |
slug | string? | Identificador para URLs do cliente (ex: balcao-principal) |
description | string? | Descrição |
serviceMode | string | Modo de operação (ver abaixo) |
active | boolean | Se o terminal está ativo |
isDefault | boolean | Terminal padrão do tenant |
pin | string? | PIN de 4–6 dígitos (armazenado com hash bcrypt) |
assignedUsers | ObjectId[] | Usuários autorizados a operar este terminal |
stoneTerminalSerial | string? | Serial da maquininha Stone |
redeTerminalSerial | string? | Serial do terminal Rede |
address | string? | Endereço (para PDVs sem branch associada) |
cnpj | string? | CNPJ (para PDVs autônomos ou com CNPJ próprio) |
focusNfeToken | string? | Token Focus NFe específico deste terminal |
Índices:
{ name, tenant }— unique{ slug, tenant }— unique sparse{ branch, tenant }— listagem por filial
Modos de Serviço
| Modo | Descrição |
|---|---|
mesa | Atendimento por garçom em mesas numeradas — abre comanda por mesa |
balcao | Atendente opera o PDV para o cliente presencialmente |
auto_atendimento | Quiosque self-service — dados obrigatórios, pagamento no terminal |
balcao_cliente | Cliente faz o próprio pedido e paga no terminal (alto giro) |
Relação Branch → PDV
O campo branch associa o terminal à sua filial física. Esta associação é usada para:
- RBAC Branch Manager —
BranchScopeGuardresolveassignedBranchIds → pdvIdsvia Redis - Cash Session rollup —
Shift.branché denormalizado depdv.branchno momento da abertura - Daily Report —
GET /branches/:id/daily-reportagrega Shifts{ branch: branchId }por PDV - Cache invalidation —
create()eupdate()do PDV invalidambranch:pdvs:{branchId}no Redis
Invalidação de cache
backend/src/pdvs/pdvs.service.ts:
typescript
const BRANCH_PDVS_PREFIX = 'branch:pdvs';
// Invalida ao criar ou alterar branch/active de um PDV
await this.redis.del(`${BRANCH_PDVS_PREFIX}:${branchId}`);Pagamento com Cartão via Gateway
| Campo | Gateway | Comportamento no PaymentModal |
|---|---|---|
stoneTerminalSerial preenchido | Stone | Cria Payment Intent → envia cobrança para a maquininha física → aguarda webhook → WebSocket paymentUpdate (até 60s) |
redeTerminalSerial preenchido | Rede | Fluxo equivalente via API Rede |
| Ambos vazios | Manual | Atendente confirma manualmente no sistema |
Pré-requisito:
STONE_CLIENT_ID+STONE_CLIENT_SECRET(ou equivalentes Rede) no backend. Veja Gateways de Pagamento.
API
Listar PDVs
GET /t/:slug/pdvs
GET /t/:slug/admin/pdvs?branchId=&active=PDVs de uma Filial
GET /t/:slug/admin/branches/:branchId/pdvsCRUD
POST /t/:slug/admin/pdvs { name, slug?, serviceMode, branch?, ... }
PUT /t/:slug/admin/pdvs/:id { qualquer campo }
DELETE /t/:slug/admin/pdvs/:id
GET /t/:slug/admin/pdvs/:id