# Architecture Decision Record — Restaurant SaaS

## ADR-001: Multi-tenancy single-database

**Decisão:** Single database, single schema, com `tenant_id` em toda tabela operacional.

**Contexto:** SaaS B2B com expectativa de centenas a milhares de tenants (restaurantes), cada um com baixo volume individual. Database-per-tenant teria custo proibitivo de manutenção (migrations, backups, monitoramento N vezes).

**Consequências:**
- ✅ Operação simples, custo baixo, agregações cross-tenant fáceis para o dono do SaaS.
- ✅ Migrations rodam uma vez.
- ⚠️ Risco de vazamento entre tenants. Mitigado por global scope obrigatório via trait + testes que verificam isolamento.
- ⚠️ Queries pesadas de um tenant impactam outros. Mitigado por particionamento futuro de tabelas grandes (sale_items por mês, por exemplo).

## ADR-002: PostgreSQL ao invés de MySQL

**Decisão:** PostgreSQL 16.

**Contexto:** Sistema fiscal e financeiro exige consistência forte. PG tem JSONB nativo (útil para fiscal e configs flexíveis), particionamento declarativo, transações DDL, advisory locks (úteis para numeração fiscal), e melhor suporte a tipos como `numeric` exato.

**Consequências:**
- ✅ Melhor para o domínio.
- ⚠️ Time precisa conhecer PG (não é MySQL).

## ADR-003: Inertia + Vue 3 + TypeScript

**Decisão:** Painel admin é Inertia + Vue 3 + TS, NÃO SPA puro com API separada.

**Contexto:** Time pequeno, deploy unificado, sem necessidade de mobile nativo no MVP. Inertia dá produtividade de monolito com UX de SPA.

**Consequências:**
- ✅ Um único deploy, um único repo.
- ✅ Auth simplificada (cookie de sessão).
- ⚠️ Para PWA garçom e site delivery, fazemos apps Vue 3 separados consumindo API REST/Sanctum.

## ADR-004: UUID v7 como PK

**Decisão:** UUID v7 em todas as tabelas operacionais.

**Contexto:** Multi-tenant com geração distribuída futura, IDs não devem ser adivinháveis, ordenação temporal é desejável.

**Consequências:**
- ✅ Seguro, ordenável, distribuível.
- ⚠️ 16 bytes vs 8 bytes do bigint. Aceitável para o volume previsto.

## ADR-005: Filas para tudo que não é resposta direta

**Decisão:** Fiscal, impressão, integrações externas, emails, webhooks — TUDO em fila.

**Contexto:** SEFAZ pode demorar 30s. Impressora pode estar offline. iFood pode timeout. Nenhum deles pode bloquear UX.

**Consequências:**
- ✅ UX rápida e resiliente.
- ⚠️ Complexidade operacional (Horizon, monitoramento de filas, retry policies).

## ADR-006: Realtime via Reverb (não Pusher)

**Decisão:** Laravel Reverb (auto-hospedado) para WebSockets.

**Contexto:** KDS, status de mesa, status de pedido delivery, notificação push para PWA — tudo precisa de realtime. Pusher cobra por conexão e ficaria caro.

**Consequências:**
- ✅ Custo previsível, sem terceiros.
- ⚠️ Operação de WebSocket server (escalar horizontalmente requer Redis pub/sub bem configurado).

## ADR-007: Estrutura modular por domínio

**Decisão:** `app/Modules/{Domain}/` com Controllers, Models, Actions, Services, Routes próprios.

**Contexto:** Sistema grande (8 fases de módulos). Estrutura padrão Laravel (`app/Models`, `app/Http/Controllers`) vira sopa em projeto desse tamanho.

**Consequências:**
- ✅ Fronteiras claras entre domínios.
- ✅ Facilita extrair microsserviço no futuro se necessário.
- ⚠️ Time precisa respeitar fronteiras (não importar Model de outro módulo direto, usar Service ou Event).

## ADR-008: Action classes ao invés de Service Layer fat

**Decisão:** Cada caso de uso = 1 Action class. Services só para lógica reutilizável entre Actions.

**Contexto:** Service classes gigantes viram lixeira em projeto grande. Action é objetivo: faz uma coisa só.

**Consequências:**
- ✅ Testabilidade alta, SRP respeitado.
- ✅ Fácil paralelizar trabalho do time.
- ⚠️ Muitas classes pequenas (preço aceitável).

## ADR-009: Money como decimal(15,4) + casts

**Decisão:** Nunca float. Decimal no DB, brick/money ou cast custom no PHP.

**Contexto:** Fiscal exige precisão exata. Float causa erro de centavo em multiplicação/divisão (ex: 1/3 do valor de pizza meio-a-meio).

**Consequências:**
- ✅ Sem bug de centavo.
- ⚠️ Cuidado constante em conversões.

## ADR-010: Fiscal via NFePHP

**Decisão:** Lib NFePHP/sped-* para emissão fiscal.

**Contexto:** Padrão de mercado, mantida ativamente, suporta NFC-e, NF-e, NFS-e, MDF-e, contingência. Alternativas (Tecnospeed, Migrate, Plug Notes) são pagas e adicionariam dependência externa.

**Consequências:**
- ✅ Sem custo de transação adicional.
- ⚠️ Time é responsável por acompanhar mudanças de layout SEFAZ.

## ADR-011: Sem TEF/Pinpad nativo no MVP

**Decisão:** MVP suporta apenas: dinheiro, Pix (QR estático ou dinâmico via gateway), cartão (digitação manual no PDV ou maquininha standalone fora do fluxo).

**Contexto:** TEF (SiTef, PayGo) requer homologação por adquirente, instalação client-side complexa. Para MVP, QR Pix dinâmico via Asaas ou Iugu cobre o caso moderno.

**Consequências:**
- ✅ Foco no que importa para 90% dos restaurantes hoje.
- ⚠️ Restaurantes que exigem TEF não vão adotar até v2.

## ADR-012: Idioma e localização

**Decisão:** pt-BR como único idioma do MVP. i18n configurado desde o dia 1 mas sem outras línguas.

**Consequências:**
- ✅ Foco no Brasil.
- ✅ Adicionar outro idioma é só traduzir, sem refactor.
