# La Vicc — Gestor + Club

Monólito **Laravel 13** (PHP 8.3+) com dois módulos por subdomínio compartilhando o mesmo banco **MySQL/MariaDB**:

| Módulo | Domínio local | Descrição |
|--------|---------------|-----------|
| **Gestor** | `gestor.lavicc.test` | Cadastro, ciclo, acertos, financeiro |
| **Club** | `club.lavicc.test` | Programa de fidelidade (revendedoras) |

Integração **Jueri** (ERP) como fonte de revendedoras, pedidos, vendas e financeiro. Protótipos de referência em [`andre/`](andre/).

## Comandos

| Comando | Uso |
|---------|-----|
| `composer test` | Testes (PHPUnit + SQLite in-memory) |
| `composer dev` | Serve + queue + pail + Vite |
| `npm run dev` | Vite (fluxo XAMPP habitual) |
| `php artisan jueri:sync [tipo]` | Sync manual Jueri |
| `php artisan schedule:work` | Scheduler (sync a cada 15 min) |
| `php artisan queue:work` | Processar jobs |
| `./vendor/bin/pint` | Formatação PHP |

Setup local, vhosts, seeds e usuários demo: ver [README.md](README.md).

## Arquitetura

```
app/
├── Livewire/Gestor|Club/     # páginas full-page (#[Layout])
├── Services/Gestor|Club/     # regra de negócio (preferir aqui)
├── Jobs/Jueri|Club/          # async / batch
├── Integrations/Jueri/       # client + sync
├── Models/                   # Club* prefixado; Gestor sem prefixo
├── Enums/                    # status com label()
└── Exceptions/Club/          # violações de regra de domínio
```

Rotas por domínio em [`bootstrap/app.php`](bootstrap/app.php) → [`routes/gestor.php`](routes/gestor.php) / [`routes/club.php`](routes/club.php).

Domínios configuráveis em [`config/domains.php`](config/domains.php). Middleware: `gestor`, `club`, `role`.

**Gestor:** dashboard, cadastro, ciclo, acertos, receitas, despesas, fluxo, inadimplência, analítico, relatórios.

**Club:** componente principal [`ClubHome`](app/Livewire/Club/ClubHome.php) com abas revendedora, operador e admin.

**Jueri:** sync agendado + `php artisan jueri:sync`; webhook `POST /integrations/jueri/webhook`. Jobs em [`app/Jobs/Jueri/`](app/Jobs/Jueri/) estendem `BaseJueriSyncJob`.

## Convenções de código

- **Lógica de negócio** em Services; Livewire orquestra UI e chama services — não duplicar regras em componentes.
- **Termos de domínio em português**: revendedora, maleta, acerto, inadimplência, resgate.
- **Configuração dinâmica**: [`RegraGestor::get()`](app/Models/RegraGestor.php) / `::set()` — chaves JSON em `regras_gestor`; não hardcodar prazos ou pontuação se já existem regra.
- **Jueri**: entidades com `jueri_id`, `jueri_payload`, `jueri_synced_at`.
- **Auth**: `User` com `role`, `module` (`gestor`|`club`|`both`), `revendedora_id`, `ativo`; Club bloqueia usuários inativos via [`EnsureClubUser`](app/Http/Middleware/EnsureClubUser.php).
- **Frontend**: Tailwind + CSS por módulo ([`resources/css/club.css`](resources/css/club.css), [`gestor.css`](resources/css/gestor.css)); Tabler Icons via CDN.
- **Escopo mínimo**: diff focado; sem refatorações não solicitadas; comentários só para regra de negócio não óbvia.

## Testes

- **PHPUnit** (não Pest); `RefreshDatabase` em feature tests.
- Club: trait [`CreatesClubFixtures`](tests/Feature/Club/Concerns/CreatesClubFixtures.php) para seed de níveis/membro; preferir chamar services/jobs diretamente.
- Exemplo: `php artisan test tests/Feature/Club/ClubNivelTempoTest.php`
- Cobertura Gestor ainda limitada — novos testes seguem o padrão Club quando possível.

## Gotchas

Pontos que costumam gerar implementação errada:

- **Troca de maleta**: pontua na **baixa** do pedido (automação `troca_prazo`), sem prazo por nível. **Não** é tolerância de inatividade. Detalhes: [`docs/club-prazo-troca.md`](docs/club-prazo-troca.md).
- **Inatividade/exclusão**: regras separadas — horas globais sem maleta + `dias_sem_maleta_exclusao` por nível; jobs em [`app/Jobs/Club/`](app/Jobs/Club/).
- **Reativação anual**: `reativacoes_max_anuais` por nível; exceção [`ReativacaoBloqueadaException`](app/Exceptions/Club/ReativacaoBloqueadaException.php).
- **Dois subdomínios**: alterações de rota/auth devem respeitar `config/domains.php` e o middleware correto (`gestor` vs `club`).
- **Sessões isoladas**: `ConfigureModuleSession` define cookie host-only e nome distinto por host (`lavicc-gestor-session` / `lavicc-club-session`); não há SSO entre módulos — login separado em cada subdomínio.
- **Não commitar** `.env`.

## Documentação relacionada

- Setup humano: [README.md](README.md)
- Regra de negócio Club (maleta / pontuação): [docs/club-prazo-troca.md](docs/club-prazo-troca.md)
- Protótipos UI: `andre/LaViccGestor.html`, `andre/LaViccClub.html`
