# Configuração local

## 1. Dependências

Instale Node.js 20.18.1 ou superior e depois execute:

```bash
npm install
```

## 2. Ambiente

Copie o ficheiro de exemplo para o ambiente local:

```powershell
if (-not (Test-Path .env)) { Copy-Item .env.example .env }
```

Configure `MYSQL_DATABASE_URL` para a base MariaDB/MySQL do XAMPP. O `.env` é
lido pelo Next.js e pela CLI do Prisma e já está coberto pelo `.gitignore`. Não
coloque credenciais reais em ficheiros versionados. O PostgreSQL local anterior
não é mais usado nem apagado; os seus dados permanecem onde estão e não são
migrados automaticamente.

## 3. Base de dados

Inicie MySQL no painel do XAMPP e crie uma base vazia chamada `pedela_local`
(por exemplo, através do phpMyAdmin). O valor predefinido no `.env.example`
usa o utilizador `root` sem password, conforme a instalação XAMPP comum; se
configurou uma password ou utilizador dedicado, atualize `MYSQL_DATABASE_URL`.
Confirme que a base de destino está vazia antes da primeira instalação; não
use a base antiga PostgreSQL como destino.

Gere o cliente Prisma MySQL e crie o schema:

```bash
npm run db:generate
```

Para uma base nova, crie-a no painel MySQL do cPanel, atribua-lhe um utilizador
com permissões e selecione-a no phpMyAdmin antes de importar
[`prisma/mysql-schema.sql`](./prisma/mysql-schema.sql). O utilizador MySQL do
cPanel não pode criar bases por SQL. Depois registe o baseline das migrations:

```bash
npx prisma migrate resolve --applied 20261018000000_init
npx prisma migrate resolve --applied 20261018132000_align_existing_mysql_schema
npx prisma migrate resolve --applied 20261018212500_customer_sessions
npm run db:status
npm run dev
```

Use este baseline apenas depois de importar o SQL numa base nova e vazia. Depois,
`db:deploy` aplica migrations futuras sem gerar migrations novas. Use
`db:migrate` apenas no desenvolvimento ao criar uma migration. `db:status`
consulta o estado das migrations. Para atualizar uma base existente, não
importe novamente o SQL nem marque migrations como aplicadas: faça backup e
revise o schema antes de usar migrations.
O comando opcional `npm run db:seed` insere/atualiza um restaurante e menu de
demonstração, mas não cria utilizadores; pode ser executado mais de uma vez.
Numa base nova, crie a primeira e única conta inicial em `/superadmin/setup` usando
`SUPERADMIN_BOOTSTRAP_SECRET`. Remova essa chave após a criação. Não configure
`ADMIN_BOOTSTRAP_SECRET` para manter o bootstrap inicial apenas no Superadmin.

Se a base MySQL já contiver tabelas ou dados, não execute `db:migrate` nem
`db:deploy` antes de fazer backup e comparar o schema com
`npx prisma migrate diff --from-schema-datasource prisma/schema.prisma --to-schema-datamodel prisma/schema.prisma`.
Uma migration inicial só pode ser marcada como aplicada quando o schema
existente corresponder exatamente ao baseline; nunca remova dados para contornar
uma divergência.

Todos os comandos Prisma (`db:generate`, `db:migrate`, `db:deploy`, `db:status`
e `db:seed`) usam exclusivamente `MYSQL_DATABASE_URL` e o schema
`prisma/schema.prisma`. A sincronização `db:push` não faz parte do fluxo
suportado; alterações de modelo devem ser versionadas como migrations.
As atualizações operacionais usam polling MySQL/HTTP a cada 15 segundos; não
dependem de ligações SSE permanentes.
O diretório `prisma/migrations` contém o histórico MySQL ativo. O histórico
PostgreSQL antigo foi preservado em `prisma/postgresql-migrations` e não é
utilizado.

`npm run db:backfill` é uma operação opcional para associar encomendas antigas
a contas de cliente depois da migration correspondente. Só deve ser executada
numa base com dados existentes, após backup e revisão; não é necessária numa
base nova e nunca é executada automaticamente.

## Billing da plataforma

O superadmin gere planos mensais, assinaturas por restaurante, faturas e
registos manuais de pagamentos em `/superadmin`. O relatório CSV exporta as
faturas e os recebimentos registados. Estes pagamentos são cobranças da
plataforma aos restaurantes e são independentes dos pagamentos dos pedidos dos
clientes.

Não existe integração automática com M-Pesa, e-Mola, bancos ou outro
processador: confirme o recebimento antes de o registar no painel. Aplique as
alterações de schema com migrations MySQL através de `npm run db:deploy`. Os
planos e preços devem ser definidos no painel; nenhum preço comercial é
presumido pelo código.

Cada plano também pode definir os máximos de utilizadores e itens de menu.
Deixe o respetivo campo vazio para não aplicar limite. Utilizadores ativos e
convites ainda válidos ocupam vagas; todos os produtos contam, mesmo quando
estão ocultos ou indisponíveis. Reduzir um limite não remove dados existentes,
mas impede novas criações até o uso ficar dentro do plano.

Assinaturas em atraso continuam a aceitar novos pedidos durante sete dias a
partir da data em que passam para `PAST_DUE`; depois disso, o checkout é
bloqueado. Assinaturas canceladas ou suspensas e períodos de teste expirados
barram novos pedidos imediatamente. O acesso das equipas ao painel permanece
disponível para gerir a conta e resolver a situação. A migration define o início
do período de tolerância para assinaturas que já estavam em atraso quando foi
aplicada.

O relatório de vendas está disponível na área de administração. Considera como
vendas apenas o total de pedidos marcados como entregues; pedidos cancelados
são apresentados separadamente e os produtos populares usam os mesmos pedidos
entregues. O intervalo selecionado está limitado a 31 dias. Estes valores não
representam pagamentos efetivamente recebidos.

`/api/health` verifica a ligação à base de dados e devolve HTTP 503 quando a
verificação falha. O painel superadmin também mostra esse estado enquanto está
aberto. Configure um monitor externo para consultar o endpoint e alertar sobre
falhas. O endpoint não verifica backups nem entrega de notificações: backups
precisam de uma rotina externa testada, e falhas de envio ainda não são
persistidas como eventos consultáveis no painel.

Com o servidor ativo, visite `/r/pedela` para ver o cardápio persistido e
`/r/pedela/products/product-classic-burger` para consultar um produto com
adicionais.

## 4. Executar

```bash
npm run dev
```

## 5. Testar o fluxo de pedidos

Em desenvolvimento, abra `/atendente/pedela/login` para autenticar e entrar na
área da equipa; `/atendente/pedela` mostra a caixa de entrada e `/r/pedela`
continua como a vista do cliente. `/dev/atendimento/pedela` permanece como
atalho local legado e encaminha para o login. No painel,
ative o som através do botão. No menu, escolha um produto, adicione-o à sacola e
confirme o checkout. O novo pedido aparece no painel na próxima sincronização,
até 15 segundos depois; as mudanças de estado feitas pelo atendente atualizam
a página de acompanhamento automaticamente, sem recarregar.

O browser só permite o alerta sonoro depois da interação do atendente com
“Ativar som”. O alerta é para pedidos novos; mudanças de estado não devem
produzir o mesmo som. O atalho legado `/dev/atendimento/...` apenas encaminha
para autenticação; a caixa de entrada e os endpoints mantêm o controlo de
acesso por sessão e restaurante também em desenvolvimento.

Para criar utilizadores no ambiente local, entre como administrador em
`/admin/pedela/login` e abra a gestão da equipa em `/admin/pedela`.
Quando SMTP não está configurado em desenvolvimento, a aplicação cria o
convite na base local e mostra no painel autenticado um link de ativação de uso
único, válido por 48 horas. A pessoa convidada abre o link e define a sua
palavra-passe; em produção, convites dependem de SMTP.

Para criar a primeira conta global local, defina `SUPERADMIN_BOOTSTRAP_SECRET`
com uma chave aleatória independente de pelo menos 32 caracteres, abra
`/superadmin/setup` e remova a variável depois da criação. O superadmin inicia
sessão em `/superadmin/login`; esta conta não pertence a um restaurante. Para
testar um restaurante como superadmin, use `/admin/pedela/login` ou
`/atendente/pedela/login` com as mesmas credenciais. O superadmin pode aceder
às duas áreas de qualquer restaurante ativo; as ações e alterações de pedidos
ficam registadas com o utilizador superadmin como autor.

O cliente pode abrir `/r/pedela/pedidos` para consultar os pedidos desse
restaurante guardados no mesmo browser. Em `/cliente`, a área “Histórico e
vouchers” permite recuperar os 50 pedidos mais recentes em qualquer dispositivo
depois de confirmar um código de utilização única enviado para o email. O código
expira em 10 minutos; a sessão de histórico usa um cookie `HttpOnly` e expira
após 30 minutos. Uma nova confirmação revoga as sessões anteriores dessa conta.
O cliente pode optar por ativar o histórico após um pedido; o checkout continua
disponível sem conta. SMTP é necessário para entregar os códigos. Os hashes dos
códigos permanentes antigos são removidos pela migration MySQL de sessões. Após
cinco pedidos entregues num restaurante, se este tiver configurado um produto
de recompensa, é emitido um voucher para esse produto. Mostre o voucher à equipa
do restaurante para o resgatar; cada restaurante controla os seus próprios
marcos, produtos e vouchers.

Contas antigas que ainda só tenham telefone não são associadas automaticamente
ao histórico por telefone. A recuperação dessas contas está suspensa até existir
um processo de prova independente; os respetivos pedidos e vouchers permanecem
guardados, mas não ficam disponíveis no acesso ao histórico. Não execute uma
associação manual apenas com esses dados.

## 7. Testes ponta a ponta locais

Os testes E2E usam uma base isolada chamada `pedela_e2e`; não executam operações
de teste em `pedela_local` nem alteram a conta Superadmin existente. Inicie o
MySQL no XAMPP e confirme que `MYSQL_DATABASE_URL` em `.env` aponta para
`pedela_local` em `localhost` ou `127.0.0.1`. A conta MySQL precisa de permissão
para criar uma base de dados. Depois execute:

```powershell
npm run test:e2e:setup
npx playwright install chromium
npm run test:e2e
```

O setup cria `pedela_e2e`, aplica as migrations MySQL e prepara um restaurante,
menu e contas de teste exclusivas desse schema. Gera também `.env.e2e`, que
permanece ignorado pelo Git e pelo upload Vercel. Os testes iniciam uma instância
Next.js isolada em `127.0.0.1:3100`, usando `.next-e2e`, sem interromper o
servidor de desenvolvimento habitual em `localhost:3000`.

Os cenários cobrem a criação de um pedido pelo cliente, a confirmação pelo
atendente e o acesso protegido do Superadmin. As credenciais E2E são locais e
fixas apenas na base `pedela_e2e`; não as reutilize em `pedela_local` ou em
qualquer ambiente publicado. Para reiniciar a base de testes, remova somente
`pedela_e2e` no phpMyAdmin e volte a executar `npm run test:e2e:setup`.

## 8. Validar

```bash
npm run lint
npm run typecheck
npm test
npm run build
```

## Preparar uma exportação para produção

Execute localmente, em Windows:

```powershell
npm ci
npm run check:production
npm run export:source
```

`check:production` só termina com sucesso quando lint, TypeScript, testes e
build passam. A exportação cria um ZIP em `release/`, excluindo `.env*`
(exceto `.env.example`), `node_modules`, `.next`, caches e imagens de produto
locais. Não partilhe nem carregue o `.env` local para o servidor.

O ZIP contém o código-fonte e o lockfile, não um build executável. Faça o build
no próprio servidor ou num ambiente Linux compatível com ele: o build Windows
pode conter binários nativos incompatíveis. No servidor:

1. Extraia o ZIP numa pasta da aplicação.
2. Instale Node.js 20.18.1 ou superior e
   execute `npm ci`.
3. Configure `MYSQL_DATABASE_URL` para uma base MySQL exclusiva de produção.
   Guarde as variáveis e credenciais no gestor de segredos/ambiente do servidor,
   não no ZIP nem no repositório.
4. Configure `APP_BASE_URL` com o domínio HTTPS público e SMTP para entregar
   códigos de acesso ao histórico e convites. Configure `PRODUCT_UPLOAD_DIR`
   como diretório persistente, gravável pela aplicação e incluído na rotina de
   backup.
5. Execute `npm run db:generate`, importe
   [`prisma/mysql-schema.sql`](./prisma/mysql-schema.sql) numa base vazia,
   registe o baseline conforme a secção mCloud abaixo e execute
   `npm run build`. Depois do baseline, `db:deploy` aplica migrations futuras
   sem criar migrations novas.
6. Inicie com `npm start` e verifique `/api/health` e o fluxo de pedidos.
7. Na primeira instalação, gere uma chave `SUPERADMIN_BOOTSTRAP_SECRET` segura
   apenas no ambiente do servidor, crie a conta global em `/superadmin/setup` e
   remova a chave do ambiente imediatamente depois.
8. Não configure `ADMIN_BOOTSTRAP_SECRET`; crie contas de equipa apenas depois
   da configuração inicial do Superadmin e através do painel autenticado.
9. Configure HTTPS no proxy/servidor frontal, backups da base e das imagens e
   monitorização. O rate limit por IP usa `X-Real-IP` ou
   `X-Forwarded-For`: o proxy confiável deve substituir/remover valores
   fornecidos pelo cliente e encaminhar o IP real. Os limites de tentativas
   ficam na base MySQL partilhada entre instâncias. Faça primeiro um ensaio
   com uma base vazia de staging.

Não execute `npm run db:seed` no servidor: o seed contém dados de demonstração
e não é uma operação de deploy. O ZIP também não contém imagens carregadas
localmente; se precisar delas, transfira-as separadamente usando um canal
seguro. Os uploads de produção devem permanecer num volume persistente, fora
da pasta temporária de extração.

## mCloud Startup (cPanel)

O arranque da aplicação usa o `server.js` incluído na raiz do projeto e lê a
porta disponibilizada pelo cPanel. A configuração está preparada para o
ambiente Node.js do cPanel, mas confirme com a mCloud que o plano permite Node
20.18.1 ou superior, aplicações Next.js com renderização dinâmica, migrations
MySQL, reinício do processo e escrita persistente no diretório pessoal.

1. Crie uma base de dados e utilizador MySQL no cPanel e atribua ao utilizador
   os privilégios necessários nessa base. Anote o hostname, nome e utilizador
   exatamente como apresentados pelo cPanel.
2. Crie uma aplicação Node.js em **Setup Node.js App**:
   - versão Node.js: `20.18.1` ou superior;
   - modo: `Production`;
   - raiz da aplicação: uma pasta fora de `public_html`, por exemplo
     `/home/UTILIZADOR/pedela-app`;
   - URL: o domínio ou subdomínio HTTPS destinado à plataforma;
   - ficheiro de arranque: `server.js`.
3. Extraia o ZIP de `release/` na raiz escolhida. Não extraia o projeto para
   `public_html` nem carregue `.env`, bases de dados locais ou imagens pessoais.
4. Configure as variáveis no gestor da aplicação Node.js:
   - `MYSQL_DATABASE_URL`: ligação MySQL de produção. Codifique caracteres
     especiais da password como URL encoding;
   - `APP_BASE_URL`: domínio HTTPS público;
   - `PRODUCT_UPLOAD_DIR`: por exemplo,
     `/home/UTILIZADOR/pedela-data/products`;
   - variáveis `SMTP_*` para convites, recuperação e códigos de acesso;
   - `SUPERADMIN_BOOTSTRAP_SECRET`: temporária, apenas durante a criação da
     primeira conta.
5. Crie `PRODUCT_UPLOAD_DIR` no diretório pessoal da conta e confirme que o
   utilizador da aplicação pode escrever nele. Não use permissões `777`. Este
   diretório deve ficar fora da pasta substituída em cada deploy e ser incluído
   em backups; o ZIP de código não contém imagens carregadas.
6. No ambiente Node.js da aplicação, instale as dependências e gere o cliente:

   ```bash
   npm ci
   npm run db:generate
   ```

   No phpMyAdmin, selecione a base criada no cPanel e importe
   [`prisma/mysql-schema.sql`](./prisma/mysql-schema.sql). O script cria apenas
   tabelas e índices; a base tem de existir e estar selecionada antes da
   importação. Depois, na raiz da aplicação e usando a mesma
   `MYSQL_DATABASE_URL`, registe o baseline para futuras migrations:

   ```bash
   npx prisma migrate resolve --applied 20261018000000_init
   npx prisma migrate resolve --applied 20261018132000_align_existing_mysql_schema
   npx prisma migrate resolve --applied 20261018212500_customer_sessions
   npx prisma migrate status
   ```

   Faça isto apenas depois de importar o SQL numa base vazia; não execute
   `npm run db:deploy` antes ou durante esse baseline. Depois, execute:

   ```bash
   npm run build
   ```

   Confirme a base de destino antes de executar qualquer opção; nunca use a
   base local nem execute `npm run db:seed` em produção. Se o Terminal do cPanel
   não herdar as variáveis da aplicação, configure-as também na sessão usada
   para estes comandos ou num `.env` privado na raiz da aplicação, com
   permissões restritas e fora do repositório/ZIP.
7. Reinicie a aplicação pelo cPanel. Confirme `/api/health`, login, criação e
   atualização de um pedido, email transacional e upload de imagem antes de
   direcionar tráfego real. Crie o Superadmin em `/superadmin/setup` e remova
   `SUPERADMIN_BOOTSTRAP_SECRET` imediatamente depois.

O build Next.js está limitado a um worker para reduzir a concorrência de CPU e
memória. As imagens Next.js estão configuradas sem otimização no servidor para
evitar processamento de imagem em runtime; use imagens de produto já
dimensionadas.
Pedidos, acompanhamento e faturas sincronizam por HTTP a cada 15 segundos, sem
manter conexões SSE abertas nos browsers. Isto reduz processos e conexões
contínuas, mas significa que uma mudança pode demorar até 15 segundos a
aparecer.

O plano Startup indicado nas capturas tem 1 GB de memória. O build pode exceder
esse limite; se o cPanel encerrar `npm run build` por memória/processos, não
copie o build Windows. Faça o build num ambiente Linux compatível com o servidor
e publique os artefactos Linux, ou peça à mCloud uma opção de build/limites
superiores. Antes da publicação, confirme ainda limites simultâneos de
processos, conexões MySQL, tempo máximo de pedido, reinício automático e
persistência do diretório pessoal. A compatibilidade efetiva depende desses
limites, que variam por conta e precisam de confirmação da mCloud.

## Notificações WhatsApp

As notificações WhatsApp ainda não são enviadas. Antes de ativar o fluxo será
necessário escolher um provedor, configurar credenciais válidas no ambiente de
execução e recolher consentimento explícito do cliente. Para a integração
oficial com a WhatsApp Business Platform, serão necessárias credenciais:

- `WHATSAPP_ACCESS_TOKEN`
- `WHATSAPP_PHONE_NUMBER_ID`

O número que recebe os pedidos é configurado por restaurante nas definições,
separadamente das credenciais do número emissor. Não configure valores fictícios
nem trate a mensagem como enviada sem confirmação do provedor. Até à integração,
os pedidos devem permanecer disponíveis na caixa de entrada do painel.
