# Setup e Como Testar

## 1. Instalação

Este pacote contém o **código de aplicação** (app/, database/, routes/,
config/, tests/) mas não o framework Laravel em si — este ambiente de
geração não tem acesso a `packagist.org`. Passos para teres a app a
correr:

```bash
# 1. Criar o esqueleto Laravel 11 num ambiente com acesso à internet
composer create-project laravel/laravel amimak-fsm-app
cd amimak-fsm-app

# 2. Copiar para dentro deste esqueleto tudo o que está neste pacote:
#    app/, database/, routes/, config/company.php, docs/, tests/, .env.example
#    (substituir os ficheiros equivalentes que o Laravel já criou, como
#    database/seeders/DatabaseSeeder.php e routes/console.php)

# 3. Instalar os pacotes necessários
composer require spatie/laravel-permission laravel/sanctum pragmarx/google2fa

# 3b. Registar o middleware ensure.mfa em bootstrap/app.php
#     (ver bootstrap/app.middleware.snippet.php neste pacote para o trecho exacto)

# 4. Publicar configs dos pacotes
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

# 5. Configurar .env (copiar o .env.example deste pacote e ajustar
#    credenciais de BD) + gerar chave
cp .env.example .env
php artisan key:generate

# 6. Migrations + seed
php artisan migrate --seed

# 7. Correr
php artisan serve
```

## 2. Testar o fluxo principal manualmente

```bash
php artisan tinker
```

```php
// Criar um Client (inquilino) e o seu utilizador de portal
$client = \App\Models\Client::create([
    'type' => 'EMPRESA', 'name' => 'Empresa Teste Lda',
    'tax_number' => '123456789', 'status' => 'ACTIVE',
]);

$portalUser = \App\Models\User::create([
    'name' => 'João Cliente', 'email' => 'joao@empresateste.co.mz',
    'password' => bcrypt('password'), 'client_id' => $client->id,
]);
$portalUser->assignRole('Requester');

// Criar um imóvel e ligar o cliente como TENANT
$property = \App\Models\Property::create([
    'code' => 'PROP-001', 'name' => 'Edifício Central', 'type' => 'OFFICE', 'status' => 'ACTIVE',
]);

\App\Models\PropertyRelationship::create([
    'property_id' => $property->id, 'client_id' => $client->id,
    'relationship_type' => 'TENANT', 'status' => 'ACTIVE',
]);

// Criar um utilizador interno (Admin)
$admin = \App\Models\User::create([
    'name' => 'Admin AMIMAK', 'email' => 'admin@amimak.co.mz',
    'password' => bcrypt('password'), 'client_id' => null,
]);
$admin->assignRole('Admin');
```

Depois, autentica-te como `joao@empresateste.co.mz` via Sanctum e chama:

```
GET  /api/v1/portal/properties            → deve mostrar só "Edifício Central"
POST /api/v1/portal/maintenance-requests  → { "property_id": 1, "title": "Torneira a pingar" }
GET  /api/v1/portal/maintenance-requests  → deve mostrar o pedido criado
```

Autentica-te como `admin@amimak.co.mz` e chama:

```
GET  /api/v1/maintenance-requests         → vê TODOS os pedidos (incluindo o do João)
POST /api/v1/maintenance-requests/{id}/approve
```

## 3. Testes automáticos

```bash
composer require pestphp/pest pestphp/pest-plugin-laravel --dev
php artisan pest:install

php artisan test
# ou especificamente o padrão de isolamento de portal:
php artisan test --filter=PortalClientIsolationExampleTest
php artisan test --filter=QuoteApprovalFlowExampleTest
```

## 4. Módulos adicionais (Assets, Quotes, Invoices, Checklists, Dashboard, MFA)

```
GET  /api/v1/assets                              → listar equipamentos
POST /api/v1/assets                               → criar equipamento

POST /api/v1/quotes                                → { work_order_id, items: [...] }
POST /api/v1/quotes/{id}/approve                    → aprova (regista IP, user, versão)

POST /api/v1/invoices                               → { work_order_id ou quote_id, items: [...] }
POST /api/v1/invoices/{id}/approve
POST /api/v1/invoices/{id}/pay

PATCH /api/v1/work-orders/{wo}/checklist/{item}      → { is_checked: true, notes }

GET  /api/v1/dashboard                              → agregados por permissão do utilizador
GET  /api/v1/portal/dashboard                        → agregados do cliente autenticado

POST /api/v1/mfa/setup                              → devolve secret + QR code
POST /api/v1/mfa/confirm                             → { code } → activa MFA + devolve recovery codes
```

**Nota sobre MFA obrigatório**: os utilizadores com role `Admin` ou
`Finance` ficam bloqueados (403) em qualquer rota interna até activarem o
MFA — ver `app/Http/Middleware/EnsureMfaIsEnabled.php`. Para testar sem
fricção em ambiente de desenvolvimento, podes temporariamente comentar o
middleware `ensure.mfa` nas rotas em `routes/api.php`.

## 4. Checklist antes de mostrar ao cliente

- [ ] `php artisan test` — tudo verde, incluindo os testes de isolamento
- [ ] Confirmar que um utilizador de portal nunca vê `/api/v1/*` (só `/api/v1/portal/*`)
- [ ] Confirmar que `POST /api/v1/portal/maintenance-requests` rejeita
      `property_id` de um imóvel sem relação activa com o cliente
- [ ] Confirmar `config('company.name')` aparece nos emails de notificação
      (não "AMIMAK" hardcoded em nenhum ficheiro `.php`/`.blade.php`)
- [ ] `php artisan route:list --path=api` — conferir que não há rotas
      internas acessíveis sem `auth:sanctum`

## 5. Deploy em cPanel — passos finais após configurar o .env

```bash
# via SSH, dentro da pasta do projeto no servidor
php artisan key:generate          # preenche APP_KEY automaticamente
php artisan migrate --seed
php artisan config:cache
php artisan route:cache
```

Cron job obrigatório (cPanel → "Cron Jobs"), a correr a cada minuto:

```
* * * * * cd /home/CPANELUSER/amimak-fsm && php artisan schedule:run >> /dev/null 2>&1
```

Sem acesso SSH: usa o phpMyAdmin do cPanel para confirmar que as tabelas
foram criadas, e o Terminal do cPanel (se disponível em "Advanced" →
"Terminal") em vez de SSH externo — os comandos são os mesmos.

**Nunca** deixar `APP_DEBUG=true` em produção — expõe stack traces com
caminhos do servidor e potencialmente dados sensíveis.
